Changeset 80762 in vbox for trunk/src/VBox
- Timestamp:
- Sep 13, 2019 2:33:47 AM (5 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r80718 r80762 47 47 #include "VBoxDD.h" 48 48 49 49 #define LUN0 0 50 50 /** 51 51 * @name VirtIO 1.0 SCSI Host feature bits (See VirtIO 1.0 specification, Section 5.6.3) … … 71 71 #define VIRTIOSCSI_REQ_QUEUE_CNT 1 /**< Number of req queues exposed by dev. */ 72 72 #define VIRTIOSCSI_QUEUE_CNT VIRTIOSCSI_REQ_QUEUE_CNT + 2 73 #define VIRTIOSCSI_MAX_TARGETS 1 /**< Can probably determined from higher layers*/74 #define VIRTIOSCSI_MAX_LUN 1/* < VirtIO specification, section 5.6.4 */73 #define VIRTIOSCSI_MAX_TARGETS 256 /**< Default value */ 74 #define VIRTIOSCSI_MAX_LUN 256 /* < VirtIO specification, section 5.6.4 */ 75 75 #define VIRTIOSCSI_MAX_COMMANDS_PER_LUN 1 /* < T.B.D. What is a good value for this? */ 76 76 #define VIRTIOSCSI_MAX_SEG_COUNT 1024 /* < T.B.D. What is a good value for this? */ … … 196 196 // Device-writable part 197 197 uint32_t uEvent; /**< event: */ 198 uint8_t u LUN[8];/**< lun */198 uint8_t uVirtioLun[8]; /**< lun */ 199 199 uint32_t uReason; /**< reason */ 200 200 } VIRTIOSCSI_EVENT_T, *PVIRTIOSCSI_EVENT_T; … … 216 216 struct REQ_CMD_HDR 217 217 { 218 uint8_t u LUN[8];/**< lun */218 uint8_t uVirtioLun[8]; /**< lun */ 219 219 uint64_t uId; /**< id */ 220 220 uint8_t uTaskAttr; /**< task_attr */ … … 290 290 { 291 291 uint32_t uType; 292 } VIRTIOSCSI_CTRL , *PVIRTIOSCSI_CTRL_T;292 } VIRTIOSCSI_CTRL_T, *PVIRTIOSCSI_CTRL_T; 293 293 294 294 /** … … 312 312 uint32_t uType; /** type */ 313 313 uint32_t uSubtype; /** subtype */ 314 uint8_t u LUN[8];/** lun */314 uint8_t uScsiLun[8]; /** lun */ 315 315 uint64_t uId; /** id */ 316 316 // Device-writable part … … 335 335 // Device-readable part 336 336 uint32_t uType; /** type */ 337 uint8_t u LUN[8];/** lun */337 uint8_t uScsiLun[8]; /** lun */ 338 338 uint32_t uEventsRequested; /** event_requested */ 339 339 // Device-writable part … … 384 384 R3PTRTYPE(PPDMIBASE) pDrvBase; 385 385 386 /** Target LUN*/387 RTUINT i LUN;388 389 /** Target LUNDescription */390 char * psz LunName;386 /** Target number (PDM LUN) */ 387 RTUINT iTarget; 388 389 /** Target Description */ 390 char * pszTargetName; 391 391 392 392 /** Target base interface. */ … … 452 452 /** Pointer to the device instance. - R3 ptr. */ 453 453 PPDMDEVINSR3 pDevInsR3; 454 454 455 /** Pointer to the device instance. - R0 ptr. */ 455 456 PPDMDEVINSR0 pDevInsR0; 457 456 458 /** Pointer to the device instance. - RC ptr. */ 457 459 PPDMDEVINSRC pDevInsRC; 458 460 459 /** Status LUN: LEDs port interface. */461 /** Status Target: LEDs port interface. */ 460 462 PDMILEDPORTS ILeds; 461 463 462 /** Status LUN: Partner of ILeds. */464 /** Status Target: Partner of ILeds. */ 463 465 R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector; 464 466 … … 480 482 /** The event semaphore the processing thread waits on. */ 481 483 482 /** Number of ports detected */484 /** Number of targets detected */ 483 485 uint64_t cTargets; 484 486 … … 518 520 /** True if in the process of quiescing I/O */ 519 521 bool fQuiescing; 520 521 522 522 523 523 } VIRTIOSCSI, *PVIRTIOSCSI; … … 532 532 PVIRTIOSCSITARGET pTarget; /**< Target */ 533 533 uint16_t qIdx; /**< Index of queue this request arrived on */ 534 size_t cbIn; /**< Size of input descriptor chain */535 size_t cbOut; /**< Size of output descriptor chain */536 534 size_t cbPiOut; /**< Size of T10 pi in buffer */ 537 535 uint8_t *pbPiOut; /**< Address of pi out buffer */ … … 547 545 PDMMEDIAEXIOREQSCSITXDIR enmTxDir; /**< Receives transfer direction of I/O req */ 548 546 uint8_t uStatus; /**< SCSI status code */ 549 PRTSGBUF pInSgBuf; /**< Buf vector to return PDM result to VirtIO Guest */ 550 PVIRTIOSCSI_REQ_CMD_T pVirtqReq; /**< Holds guest's queued req after phys → virt trans */ 547 PVIRTIO_DESC_CHAIN_T pDescChain; /**< Prepared desc chain pulled from virtq avail ring */ 551 548 } VIRTIOSCSIREQ; 552 553 #define PTARGET_FROM_LUN_BUF(lunBuf) &pThis->aTargetInstances[lunBuf[1]];554 549 555 550 DECLINLINE(bool) isBufZero(uint8_t *pv, size_t cb) … … 675 670 #endif 676 671 677 DECLINLINE(void) virtioScsiVirtToSgPhys(PVIRTIOSCSI pThis, PRTSGBUF pSgDst, void *pvSrc, size_t cb)678 {679 while (cb)680 {681 size_t cbSeg = cb;682 RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pSgDst, &cbSeg);683 PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSrc, cbSeg);684 pvSrc = ((uint8_t *)pvSrc) + cbSeg;685 cb -= cbSeg;686 }687 }688 689 DECLINLINE(void) virtioScsiSgPhysToVirt(PVIRTIOSCSI pThis, PRTSGBUF pSgSrc, void *pvDst, size_t cb)690 {691 while (cb)692 {693 size_t cbSeg = cb;694 RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pSgSrc, &cbSeg);695 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvDst, cbSeg);696 pvDst = ((uint8_t *)pvDst) + cbSeg;697 cb -= cbSeg;698 }699 }700 701 672 /** 702 673 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf} … … 728 699 static int virtioScsiSendEvent(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uEventType, uint32_t uReason) 729 700 { 730 uint8_t uLUN = 0;731 701 732 702 VIRTIOSCSI_EVENT_T event; 733 703 event.uEvent = uEventType; 734 704 event.uReason = uReason; 735 event.u LUN[0] = 1;736 event.u LUN[1] = uTarget;737 event.u LUN[2] = (uLUN>> 8) & 0x40;738 event.u LUN[3] = uLUN& 0xff;739 event.u LUN[4] = event.uLUN[5] = event.uLUN[6] = event.uLUN[7] = 0;705 event.uVirtioLun[0] = 1; 706 event.uVirtioLun[1] = uTarget; 707 event.uVirtioLun[2] = (LUN0 >> 8) & 0x40; 708 event.uVirtioLun[3] = LUN0 & 0xff; 709 event.uVirtioLun[4] = event.uVirtioLun[5] = event.uVirtioLun[6] = event.uVirtioLun[7] = 0; 740 710 741 711 switch(uEventType) … … 743 713 case VIRTIOSCSI_T_NO_EVENT: 744 714 if (uEventType & VIRTIOSCSI_T_EVENTS_MISSED) 745 LogFunc((" Warning driver that events were missed\n", uTarget, uLUN));715 LogFunc(("(target=%d, LUN=%d) Warning driver that events were missed\n", uTarget, LUN0)); 746 716 else 747 717 LogFunc(("(target=%d, LUN=%d): Warning event info guest queued is shorter than configured\n", 748 uTarget, uLUN));718 uTarget, LUN0)); 749 719 break; 750 720 case VIRTIOSCSI_T_TRANSPORT_RESET: … … 752 722 { 753 723 case VIRTIOSCSI_EVT_RESET_REMOVED: 754 LogFunc(("(target=%d, LUN=%d): Target or LUN removed\n", uTarget, uLUN));724 LogFunc(("(target=%d, LUN=%d): Target or LUN removed\n", uTarget, LUN0)); 755 725 break; 756 726 case VIRTIOSCSI_EVT_RESET_RESCAN: 757 LogFunc(("(target=%d, LUN=%d): Target or LUN added\n", uTarget, uLUN));727 LogFunc(("(target=%d, LUN=%d): Target or LUN added\n", uTarget, LUN0)); 758 728 break; 759 729 case VIRTIOSCSI_EVT_RESET_HARD: 760 LogFunc(("(target=%d, LUN=%d): Target was reset\n", uTarget, uLUN));730 LogFunc(("(target=%d, LUN=%d): Target was reset\n", uTarget, LUN0)); 761 731 break; 762 732 } … … 765 735 char szTypeText[128]; 766 736 virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), uReason); 767 LogFunc(("(target=%d, LUN=%d): Delivering subscribed async notification %s\n", uTarget, uLUN));737 LogFunc(("(target=%d, LUN=%d): Delivering subscribed async notification %s\n", uTarget, LUN0)); 768 738 break; 769 739 case VIRTIOSCSI_T_PARAM_CHANGE: 770 740 LogFunc(("(target=%d, LUN=%d): PARAM_CHANGE sense code: 0x%x sense qualifier: 0x%x\n", 771 uTarget, uLUN, uReason & 0xff, (uReason >> 8) & 0xff));741 uTarget, LUN0, uReason & 0xff, (uReason >> 8) & 0xff)); 772 742 break; 773 743 default: 774 LogFunc(("(target=%d, LUN=%d): Unknown event type: %d, ignoring\n", uTarget, uLUN));744 LogFunc(("(target=%d, LUN=%d): Unknown event type: %d, ignoring\n", uTarget, LUN0)); 775 745 return VINF_SUCCESS; 776 746 } … … 783 753 } 784 754 785 virtioQueueGet(pThis->hVirtio, EVENTQ_IDX, true, NULL, NULL); 755 PVIRTIO_DESC_CHAIN_T pDescChain; 756 virtioQueueGet(pThis->hVirtio, EVENTQ_IDX, &pDescChain, true); 786 757 787 758 RTSGBUF reqSegBuf; … … 789 760 RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG)); 790 761 791 virtioQueuePut (pThis->hVirtio, EVENTQ_IDX, &reqSegBuf, true);762 virtioQueuePut (pThis->hVirtio, EVENTQ_IDX, &reqSegBuf, pDescChain, true); 792 763 virtioQueueSync(pThis->hVirtio, EVENTQ_IDX); 793 764 … … 800 771 RTMemFree(pReq->pbPiIn); 801 772 RTMemFree(pReq->pbDataIn); 802 RTMemFree(pReq->pVirtqReq);803 773 pTarget->pDrvMediaEx->pfnIoReqFree(pTarget->pDrvMediaEx, pReq->hIoReq); 804 774 } … … 807 777 * This is called to complete a request immediately 808 778 * 809 * @param pThis - PDM driver instance state 810 * @param qIdx - Queue index 811 * @param pRespHdr - Response header 812 * @param pbSense - Pointer to sense buffer or NULL if none. 779 * @param pThis - PDM driver instance state 780 * @param qIdx - Queue index 781 * @param pDescChain - Pointer to pre-processed descriptor chain pulled from virtq 782 * @param pRespHdr - Response header 783 * @param pbSense - Pointer to sense buffer or NULL if none. 813 784 * 814 785 * @returns virtual box status code 815 786 */ 816 static int virtioScsiReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, struct REQ_RESP_HDR *pRespHdr, uint8_t *pbSense)817 { 818 787 static int virtioScsiReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain, 788 struct REQ_RESP_HDR *pRespHdr, uint8_t *pbSense) 789 { 819 790 uint8_t *abSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize); 820 791 AssertReturn(abSenseBuf, VERR_NO_MEMORY); … … 840 811 pRespHdr->uResponse = VIRTIOSCSI_S_RESET; 841 812 842 virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, true /* fFence */);813 virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, pDescChain, true /* fFence */); 843 814 virtioQueueSync(pThis->hVirtio, qIdx); 844 815 … … 861 832 RT_NOREF(pInterface); 862 833 863 PVIRTIOSCSIREQ pReq= (PVIRTIOSCSIREQ)pvIoReqAlloc;864 PVIRTIOSCSITARGET pTarget = pReq->pTarget;865 PVIRTIOSCSI pThis= pTarget->pVirtioScsi;866 PPDMIMEDIAEX pIMediaEx = pTarget->pDrvMediaEx;834 PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc; 835 PVIRTIOSCSITARGET pTarget = pReq->pTarget; 836 PVIRTIOSCSI pThis = pTarget->pVirtioScsi; 837 PPDMIMEDIAEX pIMediaEx = pTarget->pDrvMediaEx; 867 838 868 839 size_t cbResidual = 0, cbXfer = 0; … … 937 908 { 938 909 LogFunc(("cbDataIn = %u, cbDataOut = %u (cbIn = %u, cbOut = %u)\n", 939 pReq->cbDataIn, pReq->cbDataOut, pReq-> cbIn, pReq->cbOut));910 pReq->cbDataIn, pReq->cbDataOut, pReq->pDescChain->cbPhysDst, pReq->pDescChain->cbVirtSrc)); 940 911 LogFunc(("xfer = %d, residual = %u\n", cbXfer, cbResidual)); 941 912 LogFunc(("xfer direction: %s, sense written = %d, sense size = %d\n", … … 984 955 respHdr.uResponse = VIRTIOSCSI_S_OVERRUN; 985 956 respHdr.uResidual = pReq->cbDataIn; 986 virtioScsiReqErr(pThis, pReq->qIdx, &respHdr, abSense); 957 958 virtioScsiReqErr(pThis, pReq->qIdx, pReq->pDescChain, &respHdr, abSense); 987 959 return VINF_SUCCESS; 988 960 } … … 1016 988 */ 1017 989 size_t cbReqSgBuf = RTSgBufCalcTotalLength(&reqSegBuf); 1018 size_t cbInSgBuf = RTSgBufCalcTotalLength(pReq->pInSgBuf);1019 AssertMsgReturn(cbReqSgBuf <= cbInSgBuf,1020 ("Guest expected less req data (space needed: %d, avail: %d)\n", cbReqSgBuf, cbInSgBuf),990 AssertMsgReturn(cbReqSgBuf <= pReq->pDescChain->cbPhysDst, 991 ("Guest expected less req data (space needed: %d, avail: %d)\n", 992 cbReqSgBuf, pReq->pDescChain->cbPhysDst), 1021 993 VERR_BUFFER_OVERFLOW); 1022 994 1023 virtioQueuePut(pThis->hVirtio, pReq->qIdx, &reqSegBuf, true /* fFence TBD */);995 virtioQueuePut(pThis->hVirtio, pReq->qIdx, &reqSegBuf, pReq->pDescChain, true /* fFence TBD */); 1024 996 virtioQueueSync(pThis->hVirtio, pReq->qIdx); 1025 997 … … 1036 1008 } 1037 1009 1038 1039 static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PRTSGBUF pInSgBuf, PRTSGBUF pOutSgBuf) 1040 { 1041 AssertMsgReturn(pOutSgBuf->cSegs, ("Req. has no OUT data, unexpected/TBD\n"), VERR_INVALID_PARAMETER); 1042 1010 static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain) 1011 { 1043 1012 ASMAtomicIncU32(&pThis->cActiveReqs); 1044 1013 1045 size_t cbOut = RTSgBufCalcTotalLength(pOutSgBuf); 1046 size_t cbIn = RTSgBufCalcTotalLength(pInSgBuf); 1047 1048 PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)RTMemAlloc(cbOut); 1049 AssertReturn(pVirtqReq, VERR_NO_MEMORY); 1050 1051 virtioScsiSgPhysToVirt(pThis, pOutSgBuf, pVirtqReq, cbOut); 1052 1053 uint8_t uTarget = pVirtqReq->cmdHdr.uLUN[1]; 1054 uint32_t uLUN = (pVirtqReq->cmdHdr.uLUN[2] << 8 | pVirtqReq->cmdHdr.uLUN[3]) & 0x3fff; 1014 PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)pDescChain->pVirtSrc; 1015 1016 uint8_t uTarget = pVirtqReq->cmdHdr.uVirtioLun[1]; 1017 uint32_t uScsiLun = (pVirtqReq->cmdHdr.uVirtioLun[2] << 8 | pVirtqReq->cmdHdr.uVirtioLun[3]) & 0x3fff; 1018 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[uTarget]; 1055 1019 1056 1020 LogFunc(("[%s] (Target: %d LUN: %d) CDB: %.*Rhxs\n", 1057 SCSICmdText(pVirtqReq->uCdb[0]), uTarget, u LUN,1021 SCSICmdText(pVirtqReq->uCdb[0]), uTarget, uScsiLun, 1058 1022 virtioScsiEstimateCdbLen(pVirtqReq->uCdb[0], 1059 1023 pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb)); … … 1061 1025 Log3Func(("id: %RX64, attr: %x, prio: %d, crn: %x\n", 1062 1026 pVirtqReq->cmdHdr.uId, pVirtqReq->cmdHdr.uTaskAttr, pVirtqReq->cmdHdr.uPrio, pVirtqReq->cmdHdr.uCrn)); 1063 1064 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[uTarget];1065 1027 1066 1028 /* … … 1078 1040 } 1079 1041 1080 off_t uDataOutOff = sizeof(REQ_CMD_HDR) + pThis->virtioScsiConfig.uCdbSize 1042 off_t uDataOutOff = sizeof(REQ_CMD_HDR) + pThis->virtioScsiConfig.uCdbSize + cbPiHdr; 1081 1043 off_t uDataInOff = sizeof(REQ_RESP_HDR) + pThis->virtioScsiConfig.uSenseSize + cbPiIn; 1082 1044 uint8_t *pbDataOut = (uint8_t *)((uint64_t)pVirtqReq + uDataOutOff); 1083 size_t cbDataOut = cbOut- uDataOutOff;1084 size_t cbDataIn = cbIn- uDataInOff;1045 size_t cbDataOut = pDescChain->cbVirtSrc - uDataOutOff; 1046 size_t cbDataIn = pDescChain->cbPhysDst - uDataInOff; 1085 1047 1086 1048 /** … … 1095 1057 respHdr.uResponse = VIRTIOSCSI_S_RESET; 1096 1058 respHdr.uResidual = cbDataIn + cbDataOut; 1097 virtioScsiReqErr(pThis, qIdx, &respHdr, NULL); 1098 RTMemFree(pVirtqReq); 1059 virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr, NULL); 1099 1060 return VINF_SUCCESS; 1100 1061 } 1101 1062 else 1102 if (uTarget >= pThis->cTargets || u LUN!= 0)1103 { 1104 Log2Func(("Error submitting request to bad target (%d) or bad LUN (%d)\n", uTarget, u LUN));1063 if (uTarget >= pThis->cTargets || uScsiLun != 0) 1064 { 1065 Log2Func(("Error submitting request to bad target (%d) or bad LUN (%d)\n", uTarget, uScsiLun)); 1105 1066 uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED, 1106 1067 0, SCSI_SENSE_ILLEGAL_REQUEST, … … 1111 1072 respHdr.uResponse = (uTarget > pThis->cTargets) ? VIRTIOSCSI_S_BAD_TARGET : VIRTIOSCSI_S_OK; 1112 1073 respHdr.uResidual = cbDataOut + cbDataIn; 1113 virtioScsiReqErr(pThis, qIdx, &respHdr, abSense); 1114 RTMemFree(pVirtqReq); 1074 virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr, abSense); 1115 1075 return VINF_SUCCESS; 1116 1076 } … … 1126 1086 respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE; 1127 1087 respHdr.uResidual = cbDataIn + cbDataOut; 1128 virtioScsiReqErr(pThis, qIdx, &respHdr, abSense); 1129 RTMemFree(pVirtqReq); 1088 virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr , abSense); 1130 1089 return VINF_SUCCESS; 1131 1090 } … … 1151 1110 pReq->pbPiOut = (uint8_t *)((uint64_t)pVirtqReq + piOutOff); 1152 1111 pReq->cbPiIn = cbPiIn; 1153 pReq->pbPiIn = (uint8_t *)RTMemAlloc Z(cbPiIn);1112 pReq->pbPiIn = (uint8_t *)RTMemAlloc(cbPiIn); 1154 1113 AssertMsgReturn(pReq->pbPiIn, ("Out of memory allocating pi_in buffer"), VERR_NO_MEMORY); 1155 1114 } 1156 1115 1157 pReq->hIoReq = hIoReq; 1158 pReq->pTarget = pTarget; 1159 pReq->qIdx = qIdx; 1160 pReq->cbIn = cbIn; 1161 pReq->cbOut = cbOut; 1162 pReq->cbDataOut = cbDataOut; 1163 pReq->pbDataOut = cbDataOut ? pbDataOut : 0; 1164 pReq->pVirtqReq = pVirtqReq; 1165 pReq->pInSgBuf = pInSgBuf; 1166 pReq->cbSense = pThis->virtioScsiConfig.uSenseSize; 1167 pReq->pbSense = (uint8_t *)RTMemAllocZ(pReq->cbSense); 1116 pReq->hIoReq = hIoReq; 1117 pReq->pTarget = pTarget; 1118 pReq->qIdx = qIdx; 1119 pReq->cbDataOut = cbDataOut; 1120 pReq->pbDataOut = cbDataOut ? pbDataOut : 0; 1121 pReq->pDescChain = pDescChain; 1122 pReq->cbSense = pThis->virtioScsiConfig.uSenseSize; 1123 pReq->pbSense = (uint8_t *)RTMemAlloc(pReq->cbSense); 1168 1124 AssertMsgReturn(pReq->pbSense, ("Out of memory allocating sense buffer"), VERR_NO_MEMORY); 1169 1125 … … 1171 1127 { 1172 1128 pReq->cbDataIn = cbDataIn; 1173 pReq->pbDataIn = (uint8_t *)RTMemAlloc Z(cbDataIn);1129 pReq->pbDataIn = (uint8_t *)RTMemAlloc(cbDataIn); 1174 1130 AssertMsgReturn(pReq->pbDataIn, ("Out of memory allocating datain buffer"), VERR_NO_MEMORY); 1175 1131 } 1176 1132 1177 rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, u LUN,1133 rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, uScsiLun, 1178 1134 pVirtqReq->uCdb, pThis->virtioScsiConfig.uCdbSize, 1179 1135 PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, &pReq->enmTxDir, … … 1209 1165 respHdr.uResponse = VIRTIOSCSI_S_FAILURE; 1210 1166 respHdr.uResidual = cbDataIn + cbDataOut; 1211 virtioScsiReqErr(pThis, qIdx, &respHdr, abSense);1167 virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr, abSense); 1212 1168 virtioScsiFreeReq(pTarget, pReq); 1213 1169 return VINF_SUCCESS; … … 1217 1173 } 1218 1174 1219 static int virtioScsiCtrl(PVIRTIOSCSI pThis, uint16_t qIdx, PRTSGBUF pInSgBuf, PRTSGBUF pOutSgBuf) 1220 { 1221 RT_NOREF3(pThis, qIdx, pInSgBuf); 1222 1223 /* 1224 * According to the VirtIO 1.0 SCSI Host device, spec, section 5.6.6.2, control packets are 1225 * extremely small, so more than one segment is highly unlikely but not a bug. Get the 1226 * the controlq sg buffer into virtual memory. */ 1227 1228 size_t cbOut = RTSgBufCalcTotalLength(pOutSgBuf); 1229 1230 PVIRTIOSCSI_CTRL_T pScsiCtrl = (PVIRTIOSCSI_CTRL_T)RTMemAllocZ(cbOut); 1231 AssertMsgReturn(pScsiCtrl, ("Out of memory"), VERR_NO_MEMORY); 1232 1233 virtioScsiSgPhysToVirt(pThis, pOutSgBuf, pScsiCtrl, cbOut); 1175 static int virtioScsiCtrl(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain) 1176 { 1177 RT_NOREF2(pThis, qIdx); 1234 1178 1235 1179 uint8_t uResponse = VIRTIOSCSI_S_OK; 1180 1181 PVIRTIOSCSI_CTRL_T pScsiCtrl = (PVIRTIOSCSI_CTRL_T)pDescChain->pVirtSrc; 1236 1182 1237 1183 /* … … 1253 1199 PVIRTIOSCSI_CTRL_TMF_T pScsiCtrlTmf = (PVIRTIOSCSI_CTRL_TMF_T)pScsiCtrl; 1254 1200 LogFunc(("%s, VirtIO LUN: %.8Rhxs\n%*sTask Mgt Function: %s (not yet implemented)\n", 1255 QUEUENAME(qIdx), pScsiCtrlTmf->u LUN,1201 QUEUENAME(qIdx), pScsiCtrlTmf->uScsiLun, 1256 1202 CBQUEUENAME(qIdx) + 18, "", virtioGetTMFTypeText(pScsiCtrlTmf->uSubtype))); 1257 1203 … … 1305 1251 1306 1252 LogFunc(("%s, VirtIO LUN: %.8Rhxs\n%*sAsync Query, types: %s\n", 1307 QUEUENAME(qIdx), pScsiCtrlAnQuery->u LUN, CBQUEUENAME(qIdx) + 30, "", szTypeText));1253 QUEUENAME(qIdx), pScsiCtrlAnQuery->uScsiLun, CBQUEUENAME(qIdx) + 30, "", szTypeText)); 1308 1254 } 1309 1255 … … 1329 1275 1330 1276 LogFunc(("%s, VirtIO LUN: %.8Rhxs\n%*sAsync Subscribe, types: %s\n", 1331 QUEUENAME(qIdx), pScsiCtrlAnSubscribe->u LUN, CBQUEUENAME(qIdx) + 30, "", szTypeText));1277 QUEUENAME(qIdx), pScsiCtrlAnSubscribe->uScsiLun, CBQUEUENAME(qIdx) + 30, "", szTypeText)); 1332 1278 } 1333 1279 … … 1356 1302 1357 1303 LogFunc(("Response code: %s\n", virtioGetCtrlRespText(uResponse))); 1358 virtioQueuePut (pThis->hVirtio, qIdx, &reqSegBuf, true);1304 virtioQueuePut (pThis->hVirtio, qIdx, &reqSegBuf, pDescChain, true); 1359 1305 virtioQueueSync(pThis->hVirtio, qIdx); 1360 1306 … … 1383 1329 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1384 1330 PWORKER pWorker = &pThis->aWorker[qIdx]; 1385 PRTSGBUF pInSgBuf;1386 PRTSGBUF pOutSgBuf;1387 1331 1388 1332 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) … … 1416 1360 } 1417 1361 Log6Func(("fetching next descriptor chain from %s\n", QUEUENAME(qIdx))); 1418 rc = virtioQueueGet(pThis->hVirtio, qIdx, true, &pInSgBuf, &pOutSgBuf); 1362 PVIRTIO_DESC_CHAIN_T pDescChain; 1363 rc = virtioQueueGet(pThis->hVirtio, qIdx, &pDescChain, true); 1419 1364 if (rc == VERR_NOT_AVAILABLE) 1420 1365 { … … 1425 1370 AssertRC(rc); 1426 1371 if (qIdx == CONTROLQ_IDX) 1427 virtioScsiCtrl(pThis, qIdx, p InSgBuf, pOutSgBuf);1372 virtioScsiCtrl(pThis, qIdx, pDescChain); 1428 1373 else 1429 1374 { 1430 rc = virtioScsiReqSubmit(pThis, qIdx, p InSgBuf, pOutSgBuf);1375 rc = virtioScsiReqSubmit(pThis, qIdx, pDescChain); 1431 1376 if (RT_FAILURE(rc)) 1432 1377 { … … 1614 1559 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort); 1615 1560 PVIRTIOSCSI pThis = pTarget->pVirtioScsi; 1616 LogFunc(("LUN %d Ejected!\n", pTarget->i LUN));1561 LogFunc(("LUN %d Ejected!\n", pTarget->iTarget)); 1617 1562 if (pThis->pMediaNotify) 1618 1563 { 1619 1564 int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY, 1620 1565 (PFNRT)pThis->pMediaNotify->pfnEjected, 2, 1621 pThis->pMediaNotify, pTarget->i LUN);1566 pThis->pMediaNotify, pTarget->iTarget); 1622 1567 AssertRC(rc); 1623 1568 } … … 1686 1631 1687 1632 pThis->fQuiescing = false; 1688 #if 0 /* This should be unnecessary */ 1689 if (pThis->fResetting) 1690 { 1691 Log2Func(("Resetting VirtIO\n")); 1692 1693 1694 /* Reset virtio infrastructure */ 1695 virtioResetAll(pThis->hVirtio); 1696 1697 /* Reset locally-owned negotiable device-specific config parameters 1698 * to VirtIO spec-mandated default values */ 1699 } 1700 #endif 1633 1701 1634 return true; 1702 1635 } … … 1818 1751 void virtioScsiSetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn) 1819 1752 { 1820 LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->psz LunName, fOn ? "on" : "off"));1753 LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off")); 1821 1754 if (fOn) 1822 1755 pTarget->led.Asserted.s.fWriting = pTarget->led.Actual.s.fWriting = 1; … … 1833 1766 void virtioScsiSetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn) 1834 1767 { 1835 LogFlow(("%s virtioSetReadLed: %s\n", pTarget->psz LunName, fOn ? "on" : "off"));1768 LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off")); 1836 1769 if (fOn) 1837 1770 pTarget->led.Asserted.s.fReading = pTarget->led.Actual.s.fReading = 1; … … 1845 1778 * @returns VBox status code. 1846 1779 * @param pInterface Pointer to the interface structure containing the called function pointer. 1847 * @param i LUNThe unit which status LED we desire.1780 * @param iTarget The unit which status LED we desire. 1848 1781 * @param ppLed Where to store the LED pointer. 1849 1782 */ 1850 static DECLCALLBACK(int) virtioScsiTargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned i LUN, PPDMLED *ppLed)1783 static DECLCALLBACK(int) virtioScsiTargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed) 1851 1784 { 1852 1785 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed); 1853 if (i LUN== 0)1786 if (iTarget == 0) 1854 1787 { 1855 1788 *ppLed = &pTarget->led; … … 1865 1798 * @returns VBox status code. 1866 1799 * @param pInterface Pointer to the interface structure containing the called function pointer. 1867 * @param i LUNThe unit which status LED we desire.1800 * @param iTarget The unit which status LED we desire. 1868 1801 * @param ppLed Where to store the LED pointer. 1869 1802 */ 1870 static DECLCALLBACK(int) virtioScsiDeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned i LUN, PPDMLED *ppLed)1803 static DECLCALLBACK(int) virtioScsiDeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed) 1871 1804 { 1872 1805 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, ILeds); 1873 if (i LUN< pThis->cTargets)1874 { 1875 *ppLed = &pThis->aTargetInstances[i LUN].led;1806 if (iTarget < pThis->cTargets) 1807 { 1808 *ppLed = &pThis->aTargetInstances[iTarget].led; 1876 1809 Assert((*ppLed)->u32Magic == PDMLED_MAGIC); 1877 1810 return VINF_SUCCESS; … … 1997 1930 1998 1931 static DECLCALLBACK(int) virtioScsiQueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController, 1999 uint32_t *piInstance, uint32_t *pi LUN)1932 uint32_t *piInstance, uint32_t *piTarget) 2000 1933 { 2001 1934 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaPort); … … 2004 1937 AssertPtrReturn(ppcszController, VERR_INVALID_POINTER); 2005 1938 AssertPtrReturn(piInstance, VERR_INVALID_POINTER); 2006 AssertPtrReturn(pi LUN, VERR_INVALID_POINTER);1939 AssertPtrReturn(piTarget, VERR_INVALID_POINTER); 2007 1940 2008 1941 *ppcszController = pDevIns->pReg->szName; 2009 1942 *piInstance = pDevIns->iInstance; 2010 *pi LUN = pTarget->iLUN;1943 *piTarget = pTarget->iTarget; 2011 1944 2012 1945 return VINF_SUCCESS; … … 2046 1979 * 2047 1980 * @param pDevIns The device instance. 2048 * @param i LUNThe logical unit which is being detached.1981 * @param iTarget The logical unit which is being detached. 2049 1982 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 2050 1983 */ 2051 static DECLCALLBACK(void) virtioScsiDetach(PPDMDEVINS pDevIns, unsigned i LUN, uint32_t fFlags)1984 static DECLCALLBACK(void) virtioScsiDetach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags) 2052 1985 { 2053 1986 RT_NOREF(fFlags); 2054 1987 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 2055 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[i LUN];1988 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iTarget]; 2056 1989 2057 1990 LogFunc(("")); … … 2074 2007 * @returns VBox status code. 2075 2008 * @param pDevIns The device instance. 2076 * @param i LUNThe logical unit which is being detached.2009 * @param iTarget The logical unit which is being detached. 2077 2010 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 2078 2011 */ 2079 static DECLCALLBACK(int) virtioScsiAttach(PPDMDEVINS pDevIns, unsigned i LUN, uint32_t fFlags)2012 static DECLCALLBACK(int) virtioScsiAttach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags) 2080 2013 { 2081 2014 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 2082 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[i LUN];2015 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iTarget]; 2083 2016 int rc; 2084 2017 … … 2093 2026 /* the usual paranoia */ 2094 2027 AssertRelease(!pTarget->pDrvBase); 2095 Assert(pTarget->i LUN == iLUN);2028 Assert(pTarget->iTarget == iTarget); 2096 2029 2097 2030 /* … … 2099 2032 * required as well as optional. 2100 2033 */ 2101 rc = PDMDevHlpDriverAttach(pDevIns, pTarget->i LUN, &pDevIns->IBase,2102 &pTarget->pDrvBase, (const char *)&pTarget->psz LunName);2034 rc = PDMDevHlpDriverAttach(pDevIns, pTarget->iTarget, &pDevIns->IBase, 2035 &pTarget->pDrvBase, (const char *)&pTarget->pszTargetName); 2103 2036 if (RT_SUCCESS(rc)) 2104 2037 pTarget->fPresent = true; 2105 2038 else 2106 AssertMsgFailed(("Failed to attach %s. rc=%Rrc\n", pTarget->psz LunName, rc));2039 AssertMsgFailed(("Failed to attach %s. rc=%Rrc\n", pTarget->pszTargetName, rc)); 2107 2040 2108 2041 if (RT_FAILURE(rc)) … … 2150 2083 LogFunc(("PDM device instance: %d\n", iInstance)); 2151 2084 RTStrPrintf((char *)pThis->szInstance, sizeof(pThis->szInstance), "VIRTIOSCSI%d", iInstance); 2085 2086 /* Usable defaults */ 2087 pThis->cTargets = VIRTIOSCSI_MAX_TARGETS; 2152 2088 2153 2089 /* … … 2267 2203 2268 2204 /* Initialize per device instance. */ 2269 for (RTUINT iLUN = 0; iLUN < VIRTIOSCSI_MAX_TARGETS; iLUN++) 2270 { 2271 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN]; 2272 2273 if (RTStrAPrintf(&pTarget->pszLunName, "VSCSILUN%u", iLUN) < 0) 2205 2206 Log2Func(("Found %d targets attached to controller\n", pThis->cTargets)); 2207 2208 for (RTUINT iTarget = 0; iTarget < pThis->cTargets; iTarget++) 2209 { 2210 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iTarget]; 2211 2212 if (RTStrAPrintf(&pTarget->pszTargetName, "VSCSI%u", iTarget) < 0) 2274 2213 AssertLogRelFailedReturn(VERR_NO_MEMORY); 2275 2214 2276 2215 /* Initialize static parts of the device. */ 2277 pTarget->i LUN = iLUN;2216 pTarget->iTarget = iTarget; 2278 2217 pTarget->pVirtioScsi = pThis; 2218 pTarget->led.u32Magic = PDMLED_MAGIC; 2279 2219 2280 2220 pTarget->IBase.pfnQueryInterface = virtioScsiTargetQueryInterface; … … 2296 2236 pTarget->led.u32Magic = PDMLED_MAGIC; 2297 2237 2298 LogFunc(("Attaching LUN: %s\n", pTarget->psz LunName));2299 2300 AssertReturn(i LUN< RT_ELEMENTS(pThis->aTargetInstances), VERR_PDM_NO_SUCH_LUN);2301 rc = PDMDevHlpDriverAttach(pDevIns, i LUN, &pTarget->IBase, &pTarget->pDrvBase, (const char *)&pTarget->pszLunName);2238 LogFunc(("Attaching LUN: %s\n", pTarget->pszTargetName)); 2239 2240 AssertReturn(iTarget < RT_ELEMENTS(pThis->aTargetInstances), VERR_PDM_NO_SUCH_LUN); 2241 rc = PDMDevHlpDriverAttach(pDevIns, iTarget, &pTarget->IBase, &pTarget->pDrvBase, (const char *)&pTarget->pszTargetName); 2302 2242 if (RT_SUCCESS(rc)) 2303 2243 { 2304 2244 pTarget->fPresent = true; 2305 2245 2306 /* DrvSCSI.cpp currently implements the IMedia and IMediaEx interfaces, so those2307 * are the interfaces that will be used to pass SCSI requests down to the2308 * DrvSCSI driver to eventually make it down to the VD layer */2309 2246 pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIA); 2310 2247 AssertMsgReturn(VALID_PTR(pTarget->pDrvMedia), 2311 ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", pTarget->i LUN),2248 ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", pTarget->iTarget), 2312 2249 VERR_PDM_MISSING_INTERFACE); 2313 2250 … … 2315 2252 pTarget->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIAEX); 2316 2253 AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx), 2317 ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", pTarget->i LUN),2254 ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", pTarget->iTarget), 2318 2255 VERR_PDM_MISSING_INTERFACE); 2319 2256 2320 2257 rc = pTarget->pDrvMediaEx->pfnIoReqAllocSizeSet(pTarget->pDrvMediaEx, sizeof(VIRTIOSCSIREQ)); 2321 2258 AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx), 2322 ("virtio-scsi configuration error: LUN#%u: Failed to set I/O request size!\n", pTarget->i LUN),2259 ("virtio-scsi configuration error: LUN#%u: Failed to set I/O request size!\n", pTarget->iTarget), 2323 2260 rc); 2324 2261 … … 2326 2263 AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx), 2327 2264 ("virtio-scsi configuration error: LUN#%u: Failed to get set Media notify obj!\n", 2328 pTarget->i LUN), rc);2265 pTarget->iTarget), rc); 2329 2266 2330 2267 } … … 2334 2271 pTarget->pDrvBase = NULL; 2335 2272 rc = VINF_SUCCESS; 2336 Log(("virtio-scsi: no driver attached to device %s\n", pTarget->psz LunName));2273 Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszTargetName)); 2337 2274 } 2338 2275 else 2339 2276 { 2340 AssertLogRelMsgFailed(("virtio-scsi: Failed to attach %s \n", pTarget->pszLunName));2277 AssertLogRelMsgFailed(("virtio-scsi: Failed to attach %s: %Rrc\n", pTarget->pszTargetName)); 2341 2278 return rc; 2342 2279 } -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r80718 r80762 34 34 35 35 #define INSTANCE(pVirtio) pVirtio->szInstance 36 #define QUEUENAME(qIdx) (pVirtio->virtqProxy[qIdx].szVirtqName) 37 36 #define QUEUENAME(qIdx) (pVirtio->virtqState[qIdx].szVirtqName) 37 38 /** 39 * See API comments in header file for description 40 */ 41 void virtioVirtToSgPhys(VIRTIOHANDLE hVirtio, PRTSGBUF pSgDst, void *pvSrc, size_t cb) 42 { 43 while (cb) 44 { 45 size_t cbSeg = cb; 46 RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pSgDst, &cbSeg); 47 PDMDevHlpPhysWrite(((PVIRTIOSTATE)hVirtio)->CTX_SUFF(pDevIns), GCPhys, pvSrc, cbSeg); 48 pvSrc = ((uint8_t *)pvSrc) + cbSeg; 49 cb -= cbSeg; 50 } 51 } 52 53 /** 54 * See API comments in header file for description 55 */ 56 void virtioSgPhysToVirt(VIRTIOHANDLE hVirtio, PRTSGBUF pSgSrc, void *pvDst, size_t cb) 57 { 58 while (cb) 59 { 60 size_t cbSeg = cb; 61 RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pSgSrc, &cbSeg); 62 PDMDevHlpPhysRead(((PVIRTIOSTATE)hVirtio)->CTX_SUFF(pDevIns), GCPhys, pvDst, cbSeg); 63 pvDst = ((uint8_t *)pvDst) + cbSeg; 64 cb -= cbSeg; 65 } 66 } 38 67 39 68 /** … … 44 73 LogFunc(("%s\n", pcszName)); 45 74 PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio; 46 PVIRTQ_PROXY_T pVirtqProxy = &(pVirtio->virtqProxy[qIdx]); 47 pVirtqProxy->pDescChain = (PVIRTQ_DESC_CHAIN_T)RTMemAllocZ(sizeof(VIRTQ_DESC_CHAIN_T)); 48 if (!pVirtqProxy->pDescChain) 49 { 50 Log(("Out of memory!")); 51 return VERR_NO_MEMORY; 52 } 53 pVirtqProxy->uAvailIdx = 0; 54 pVirtqProxy->uUsedIdx = 0; 55 pVirtqProxy->fEventThresholdReached = false; 56 RTStrCopy((char *)pVirtqProxy->szVirtqName, sizeof(pVirtqProxy->szVirtqName), pcszName); 75 PVIRTQSTATE pVirtq = &(pVirtio->virtqState[qIdx]); 76 pVirtq->uAvailIdx = 0; 77 pVirtq->uUsedIdx = 0; 78 pVirtq->fEventThresholdReached = false; 79 RTStrCopy((char *)pVirtq->szVirtqName, sizeof(pVirtq->szVirtqName), pcszName); 57 80 return VINF_SUCCESS; 58 81 … … 64 87 const char *virtioQueueGetName(VIRTIOHANDLE hVirtio, uint16_t qIdx) 65 88 { 66 return (const char *)((PVIRTIOSTATE)hVirtio)->virtq Proxy[qIdx].szVirtqName;89 return (const char *)((PVIRTIOSTATE)hVirtio)->virtqState[qIdx].szVirtqName; 67 90 } 68 91 … … 72 95 int virtioQueueSkip(VIRTIOHANDLE hVirtio, uint16_t qIdx) 73 96 { 74 Assert(qIdx < sizeof(VIRTQ _PROXY_T));97 Assert(qIdx < sizeof(VIRTQSTATE)); 75 98 76 99 PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio; 77 PVIRTQ _PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];100 PVIRTQSTATE pVirtq = &pVirtio->virtqState[qIdx]; 78 101 79 102 AssertMsgReturn(DRIVER_OK(pVirtio) && pVirtio->uQueueEnable[qIdx], … … 83 106 return VERR_NOT_AVAILABLE; 84 107 85 Log2Func(("%s avail_idx=%u\n", pVirtq Proxy->szVirtqName, pVirtqProxy->uAvailIdx));86 pVirtq Proxy->uAvailIdx++;108 Log2Func(("%s avail_idx=%u\n", pVirtq->szVirtqName, pVirtq->uAvailIdx)); 109 pVirtq->uAvailIdx++; 87 110 88 111 return VINF_SUCCESS; … … 112 135 * See API comments in header file for description 113 136 */ 114 int virtioQueuePeek(VIRTIOHANDLE hVirtio, uint16_t qIdx, PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs) 115 { 116 return virtioQueueGet(hVirtio, qIdx, false /* fRemove */, ppInSegs, ppOutSegs); 117 } 118 119 /*/** 120 * See API comments in header file for description 121 */ 122 int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, bool fRemove, 123 PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs) 124 { 137 int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove) 138 { 139 Assert(ppDescChain); 140 125 141 PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio; 126 PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx]; 127 PVIRTQ_DESC_CHAIN_T pDescChain = pVirtqProxy->pDescChain; 142 PVIRTQSTATE pVirtq = &pVirtio->virtqState[qIdx]; 143 144 PRTSGSEG paSegsIn = (PRTSGSEG)RTMemAlloc(VIRTQ_MAX_SIZE * sizeof(RTSGSEG)); 145 AssertReturn(paSegsIn, VERR_NO_MEMORY); 146 147 PRTSGSEG paSegsOut = (PRTSGSEG)RTMemAlloc(VIRTQ_MAX_SIZE * sizeof(RTSGSEG)); 148 AssertReturn(paSegsOut, VERR_NO_MEMORY); 128 149 129 150 AssertMsgReturn(DRIVER_OK(pVirtio) && pVirtio->uQueueEnable[qIdx], … … 133 154 return VERR_NOT_AVAILABLE; 134 155 135 pDescChain->cSegsIn = pDescChain->cSegsOut = 0; 136 137 pDescChain->uHeadIdx = virtioReadAvailDescIdx(pVirtio, qIdx, pVirtqProxy->uAvailIdx); 138 uint16_t uDescIdx = pDescChain->uHeadIdx; 156 uint16_t uHeadIdx = virtioReadAvailDescIdx(pVirtio, qIdx, pVirtq->uAvailIdx); 157 uint16_t uDescIdx = uHeadIdx; 139 158 140 159 Log6Func(("%s DESC CHAIN: (head) desc_idx=%u [avail_idx=%u]\n", 141 pVirtq Proxy->szVirtqName, pDescChain->uHeadIdx, pVirtqProxy->uAvailIdx));160 pVirtq->szVirtqName, uHeadIdx, pVirtq->uAvailIdx)); 142 161 143 162 if (fRemove) 144 pVirtqProxy->uAvailIdx++; 145 146 uint32_t cbIn = 0, cbOut = 0; 163 pVirtq->uAvailIdx++; 164 147 165 VIRTQ_DESC_T desc; 166 167 uint32_t cbIn = 0, cbOut = 0, cSegsIn = 0, cSegsOut = 0; 168 148 169 do 149 170 { … … 151 172 152 173 /** 153 * Malicious guests may go beyond aSegsIn oraSegsOut boundaries by linking174 * Malicious guests may go beyond paSegsIn or paSegsOut boundaries by linking 154 175 * several descriptors into a loop. Since there is no legitimate way to get a sequences of 155 176 * linked descriptors exceeding the total number of descriptors in the ring (see @bugref{8620}), 156 177 * the following aborts I/O if breach and employs a simple log throttling algorithm to notify. 157 178 */ 158 if ( pDescChain->cSegsIn + pDescChain->cSegsOut >= VIRTQ_MAX_SIZE)179 if (cSegsIn + cSegsOut >= VIRTQ_MAX_SIZE) 159 180 { 160 181 static volatile uint32_t s_cMessages = 0; … … 178 199 { 179 200 Log6Func(("%s IN desc_idx=%u seg=%u addr=%RGp cb=%u\n", 180 QUEUENAME(qIdx), uDescIdx, pDescChain->cSegsIn, desc.pGcPhysBuf, desc.cb));201 QUEUENAME(qIdx), uDescIdx, cSegsIn, desc.pGcPhysBuf, desc.cb)); 181 202 cbIn += desc.cb; 182 pSeg = &(p DescChain->aSegsIn[pDescChain->cSegsIn++]);203 pSeg = &(paSegsIn[cSegsIn++]); 183 204 } 184 205 else 185 206 { 186 207 Log6Func(("%s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n", 187 QUEUENAME(qIdx), uDescIdx, pDescChain->cSegsOut, desc.pGcPhysBuf, desc.cb));208 QUEUENAME(qIdx), uDescIdx, cSegsOut, desc.pGcPhysBuf, desc.cb)); 188 209 cbOut += desc.cb; 189 pSeg = &(p DescChain->aSegsOut[pDescChain->cSegsOut++]);210 pSeg = &(paSegsOut[cSegsOut++]); 190 211 } 191 212 … … 196 217 } while (desc.fFlags & VIRTQ_DESC_F_NEXT); 197 218 198 RTSgBufInit(&pVirtqProxy->inSgBuf, (PCRTSGSEG)&pDescChain->aSegsIn, pDescChain->cSegsIn); 199 RTSgBufInit(&pVirtqProxy->outSgBuf, (PCRTSGSEG)&pDescChain->aSegsOut, pDescChain->cSegsOut); 200 201 if (ppInSegs) 202 *ppInSegs = &pVirtqProxy->inSgBuf; 203 204 if (ppOutSegs) 205 *ppOutSegs = &pVirtqProxy->outSgBuf; 219 220 PRTSGBUF pSgPhysIn = (PRTSGBUF)RTMemAllocZ(sizeof(RTSGBUF)); 221 AssertReturn(pSgPhysIn, VERR_NO_MEMORY); 222 223 RTSgBufInit(pSgPhysIn, (PCRTSGSEG)paSegsIn, cSegsIn); 224 225 void *pSgVirtOut = RTMemAlloc(cbOut); 226 AssertReturn(pSgVirtOut, VERR_NO_MEMORY); 227 228 if (cSegsOut) 229 { 230 RTSGBUF outSgPhys; 231 RTSgBufInit(&outSgPhys, (PCRTSGSEG)paSegsOut, cSegsOut); 232 virtioSgPhysToVirt((PVIRTIOSTATE)hVirtio, &outSgPhys, pSgVirtOut, cbOut); 233 RTMemFree(paSegsOut); 234 } 235 236 PVIRTIO_DESC_CHAIN_T pDescChain = (PVIRTIO_DESC_CHAIN_T)RTMemAllocZ(sizeof(VIRTIO_DESC_CHAIN_T)); 237 AssertReturn(pDescChain, VERR_NO_MEMORY); 238 239 pDescChain->uHeadIdx = uHeadIdx; 240 pDescChain->cbVirtSrc = cbOut; 241 pDescChain->pVirtSrc = pSgVirtOut; 242 pDescChain->cbPhysDst = cbIn; 243 pDescChain->pSgPhysDst = pSgPhysIn; 244 *ppDescChain = pDescChain; 206 245 207 246 Log6Func(("%s -- segs OUT: %u (%u bytes) IN: %u (%u bytes) --\n", 208 pVirtq Proxy->szVirtqName, pDescChain->cSegsOut, cbOut, pDescChain->cSegsIn, cbIn));247 pVirtq->szVirtqName, cSegsOut, cbOut, cSegsIn, cbIn)); 209 248 210 249 return VINF_SUCCESS; … … 212 251 213 252 /** See API comments in header file prototype for description */ 214 int virtioQueuePut(VIRTIOHANDLE hVirtio, uint16_t qIdx, PRTSGBUF pSg Buf, bool fFence)215 { 216 217 Assert(qIdx < sizeof(VIRTQ_PROXY_T));253 int virtioQueuePut(VIRTIOHANDLE hVirtio, uint16_t qIdx, PRTSGBUF pSgVirtReturn, 254 PVIRTIO_DESC_CHAIN_T pDescChain, bool fFence) 255 { 256 Assert(qIdx < VIRTQ_MAX_CNT); 218 257 219 258 PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio; 220 PVIRTQ _PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];221 P VIRTQ_DESC_CHAIN_T pDescChain = pVirtqProxy->pDescChain;259 PVIRTQSTATE pVirtq = &pVirtio->virtqState[qIdx]; 260 PRTSGBUF pSgPhysReturn = pDescChain->pSgPhysDst; 222 261 223 262 AssertMsgReturn(DRIVER_OK(pVirtio) /*&& pVirtio->uQueueEnable[qIdx]*/, 224 263 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 225 /** 226 * Copy caller's virtual memory sg buffer to physical memory 227 */ 228 PRTSGBUF pBufSrc = pSgBuf; 229 PRTSGBUF pBufDst = &pVirtqProxy->inSgBuf; 230 231 size_t cbRemain = RTSgBufCalcTotalLength(pBufSrc); 264 232 265 uint16_t uUsedIdx = virtioReadUsedRingIdx(pVirtio, qIdx); 233 266 Log6Func(("Copying client data to %s, desc chain (head desc_idx %d)\n", 234 267 QUEUENAME(qIdx), uUsedIdx)); 235 268 269 /* 270 * Copy virtual memory s/g buffer containing data to return to the guest 271 * to phys. memory described by (IN direction ) s/g buffer of the descriptor chain 272 * original pulled from the queue, to 'send back' to the guest driver. 273 */ 274 size_t cbRemain = RTSgBufCalcTotalLength(pSgVirtReturn); 275 size_t cbCopy = 0; 236 276 while (cbRemain) 237 277 { 238 uint64_t dstSgStart = (uint64_t)pBufDst->paSegs[pBufDst->idxSeg].pvSeg; 239 uint64_t dstSgLen = (uint64_t)pBufDst->paSegs[pBufDst->idxSeg].cbSeg; 240 uint64_t dstSgCur = (uint64_t)pBufDst->pvSegCur; 241 size_t cbCopy = RT_MIN(pBufSrc->cbSegLeft, dstSgLen - (dstSgCur - dstSgStart)); 278 PCRTSGSEG paSeg = &pSgPhysReturn->paSegs[pSgPhysReturn->idxSeg]; 279 uint64_t dstSgStart = (uint64_t)paSeg->pvSeg; 280 uint64_t dstSgLen = (uint64_t)paSeg->cbSeg; 281 uint64_t dstSgCur = (uint64_t)pSgPhysReturn->pvSegCur; 282 cbCopy = RT_MIN(pSgVirtReturn->cbSegLeft, dstSgLen - (dstSgCur - dstSgStart)); 242 283 PDMDevHlpPhysWrite(pVirtio->CTX_SUFF(pDevIns), 243 (RTGCPHYS)p BufDst->pvSegCur, pBufSrc->pvSegCur, cbCopy);244 RTSgBufAdvance(p BufSrc, cbCopy);245 RTSgBufAdvance(p BufDst, cbCopy);284 (RTGCPHYS)pSgPhysReturn->pvSegCur, pSgVirtReturn->pvSegCur, cbCopy); 285 RTSgBufAdvance(pSgVirtReturn, cbCopy); 286 RTSgBufAdvance(pSgPhysReturn, cbCopy); 246 287 cbRemain -= cbCopy; 247 288 } 289 248 290 249 291 if (fFence) … … 252 294 /** If this write-ahead crosses threshold where the driver wants to get an event flag it */ 253 295 if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX) 254 if (pVirtq Proxy->uUsedIdx == virtioReadAvailUsedEvent(pVirtio, qIdx))255 pVirtq Proxy->fEventThresholdReached = true;296 if (pVirtq->uUsedIdx == virtioReadAvailUsedEvent(pVirtio, qIdx)) 297 pVirtq->fEventThresholdReached = true; 256 298 257 299 /** 258 300 * Place used buffer's descriptor in used ring but don't update used ring's slot index. 259 301 * That will be done with a subsequent client call to virtioQueueSync() */ 260 virtioWriteUsedElem(pVirtio, qIdx, 261 pVirtqProxy->uUsedIdx++, 262 pDescChain->uHeadIdx, 263 pDescChain->cSegsIn); 302 virtioWriteUsedElem(pVirtio, qIdx, pVirtq->uUsedIdx++, pDescChain->uHeadIdx, cbCopy); 303 264 304 265 305 if (LogIs2Enabled()) 266 306 { 267 size_t cbInSgBuf = RTSgBufCalcTotalLength(pBufDst);268 size_t cbWritten = cbInSgBuf - RTSgBufCalcLengthLeft(pBufDst);269 307 Log2Func((".... Copied %u bytes to %u byte buffer, residual=%d\n", 270 cb Written, cbInSgBuf, cbInSgBuf - cbWritten));308 cbCopy, pDescChain->cbPhysDst, pDescChain->cbPhysDst - cbCopy)); 271 309 } 272 310 Log6Func(("Write ahead used_idx=%d, %s used_idx=%d\n", 273 pVirtqProxy->uUsedIdx, QUEUENAME(qIdx), uUsedIdx)); 311 pVirtq->uUsedIdx, QUEUENAME(qIdx), uUsedIdx)); 312 313 RTMemFree((void *)pSgPhysReturn->paSegs); 314 RTMemFree(pSgPhysReturn); 315 RTMemFree(pDescChain); 274 316 275 317 return VINF_SUCCESS; … … 281 323 int virtioQueueSync(VIRTIOHANDLE hVirtio, uint16_t qIdx) 282 324 { 283 Assert(qIdx < sizeof(VIRTQ _PROXY_T));325 Assert(qIdx < sizeof(VIRTQSTATE)); 284 326 285 327 PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio; 286 PVIRTQ _PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];328 PVIRTQSTATE pVirtq = &pVirtio->virtqState[qIdx]; 287 329 288 330 AssertMsgReturn(DRIVER_OK(pVirtio) && pVirtio->uQueueEnable[qIdx], … … 291 333 uint16_t uIdx = virtioReadUsedRingIdx(pVirtio, qIdx); 292 334 Log6Func(("Updating %s used_idx from %u to %u\n", 293 QUEUENAME(qIdx), uIdx, pVirtq Proxy->uUsedIdx));294 295 virtioWriteUsedRingIdx(pVirtio, qIdx, pVirtq Proxy->uUsedIdx);335 QUEUENAME(qIdx), uIdx, pVirtq->uUsedIdx)); 336 337 virtioWriteUsedRingIdx(pVirtio, qIdx, pVirtq->uUsedIdx); 296 338 virtioNotifyGuestDriver(pVirtio, qIdx, false); 297 339 … … 306 348 Assert(uNotifyIdx == qIdx); 307 349 308 PVIRTQ _PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];309 Log6Func(("%s\n", pVirtq Proxy->szVirtqName));350 PVIRTQSTATE pVirtq = &pVirtio->virtqState[qIdx]; 351 Log6Func(("%s\n", pVirtq->szVirtqName)); 310 352 311 353 /** Inform client */ … … 337 379 static void virtioNotifyGuestDriver(PVIRTIOSTATE pVirtio, uint16_t qIdx, bool fForce) 338 380 { 339 PVIRTQ _PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];381 PVIRTQSTATE pVirtq = &pVirtio->virtqState[qIdx]; 340 382 341 383 AssertMsgReturnVoid(DRIVER_OK(pVirtio), ("Guest driver not in ready state.\n")); … … 345 387 if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX) 346 388 { 347 if (pVirtq Proxy->fEventThresholdReached)389 if (pVirtq->fEventThresholdReached) 348 390 { 349 391 virtioRaiseInterrupt(pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, fForce); 350 pVirtq Proxy->fEventThresholdReached = false;392 pVirtq->fEventThresholdReached = false; 351 393 return; 352 394 } … … 434 476 static void virtioResetQueue(PVIRTIOSTATE pVirtio, uint16_t qIdx) 435 477 { 436 PVIRTQ _PROXY_T pVirtQ = &pVirtio->virtqProxy[qIdx];478 PVIRTQSTATE pVirtQ = &pVirtio->virtqState[qIdx]; 437 479 pVirtQ->uAvailIdx = 0; 438 480 pVirtQ->uUsedIdx = 0; … … 832 874 Assert(cb >= 32); 833 875 834 if (iRegion == VIRTIO SCSI_REGION_PCI_CAP)876 if (iRegion == VIRTIO_REGION_PCI_CAP) 835 877 { 836 878 /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */ … … 885 927 uint8_t uBar = pVirtio->pPciCfgCap->pciCap.uBar; 886 928 uint32_t pv = 0; 887 if (uBar == VIRTIO SCSI_REGION_PCI_CAP)929 if (uBar == VIRTIO_REGION_PCI_CAP) 888 930 (void)virtioR3MmioRead(pDevIns, NULL, (RTGCPHYS)((uint32_t)pVirtio->pGcPhysPciCapBase + uOffset), 889 931 &pv, uLength); … … 929 971 uint32_t uOffset = pVirtio->pPciCfgCap->pciCap.uOffset; 930 972 uint8_t uBar = pVirtio->pPciCfgCap->pciCap.uBar; 931 if (uBar == VIRTIO SCSI_REGION_PCI_CAP)973 if (uBar == VIRTIO_REGION_PCI_CAP) 932 974 (void)virtioR3MmioWrite(pDevIns, NULL, (RTGCPHYS)((uint32_t)pVirtio->pGcPhysPciCapBase + uOffset), 933 975 (void *)&u32Value, uLength); … … 1117 1159 pCfg->uCapLen = sizeof(VIRTIO_PCI_CAP_T); 1118 1160 pCfg->uCapNext = CFGADDR2IDX(pCfg) + pCfg->uCapLen; 1119 pCfg->uBar = VIRTIO SCSI_REGION_PCI_CAP;1161 pCfg->uBar = VIRTIO_REGION_PCI_CAP; 1120 1162 pCfg->uOffset = RT_ALIGN_32(0, 4); /* reminder, in case someone changes offset */ 1121 1163 pCfg->uLength = sizeof(VIRTIO_PCI_COMMON_CFG_T); … … 1132 1174 pCfg->uCapLen = sizeof(VIRTIO_PCI_NOTIFY_CAP_T); 1133 1175 pCfg->uCapNext = CFGADDR2IDX(pCfg) + pCfg->uCapLen; 1134 pCfg->uBar = VIRTIO SCSI_REGION_PCI_CAP;1176 pCfg->uBar = VIRTIO_REGION_PCI_CAP; 1135 1177 pCfg->uOffset = pVirtio->pCommonCfgCap->uOffset + pVirtio->pCommonCfgCap->uLength; 1136 1178 pCfg->uOffset = RT_ALIGN_32(pCfg->uOffset, 2); … … 1151 1193 pCfg->uCapLen = sizeof(VIRTIO_PCI_CAP_T); 1152 1194 pCfg->uCapNext = CFGADDR2IDX(pCfg) + pCfg->uCapLen; 1153 pCfg->uBar = VIRTIO SCSI_REGION_PCI_CAP;1195 pCfg->uBar = VIRTIO_REGION_PCI_CAP; 1154 1196 pCfg->uOffset = pVirtio->pNotifyCap->pciCap.uOffset + pVirtio->pNotifyCap->pciCap.uLength; 1155 1197 pCfg->uLength = sizeof(uint8_t); … … 1184 1226 pCfg->uCapLen = sizeof(VIRTIO_PCI_CAP_T); 1185 1227 pCfg->uCapNext = fMsiSupport ? CFGADDR2IDX(pCfg) + pCfg->uCapLen : 0; 1186 pCfg->uBar = VIRTIO SCSI_REGION_PCI_CAP;1228 pCfg->uBar = VIRTIO_REGION_PCI_CAP; 1187 1229 pCfg->uOffset = pVirtio->pIsrCap->uOffset + pVirtio->pIsrCap->uLength; 1188 1230 pCfg->uOffset = RT_ALIGN_32(pCfg->uOffset, 4); … … 1214 1256 * out size, so pad with an extra page */ 1215 1257 1216 rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIO SCSI_REGION_PCI_CAP, RT_ALIGN_32(cbRegion + 0x1000, 0x1000),1258 rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIO_REGION_PCI_CAP, RT_ALIGN_32(cbRegion + 0x1000, 0x1000), 1217 1259 PCI_ADDRESS_SPACE_MEM, virtioR3Map); 1218 1260 if (RT_FAILURE(rc)) … … 1266 1308 { 1267 1309 Log2Func(("%s queue:\n", 1268 " virtq Proxy[%u].uAvailIdx = %u\n virtqProxy[%u].uUsedIdx = %u\n"1310 " virtqState[%u].uAvailIdx = %u\n virtqState[%u].uUsedIdx = %u\n" 1269 1311 " uQueueSize[%u] = %u\n uQueueNotifyOff[%u] = %04x\n" 1270 1312 " uQueueMsixVector[%u] = %04x\n uQueueEnable[%u] = %04x\n" 1271 1313 " pGcPhysQueueDesc[%u] = %RGp\n pGcPhysQueueAvail[%u] = %RGp\n" 1272 1314 " pGcPhysQueueUsed[%u] = %RGp\n", 1273 i, pVirtio->virtq Proxy[i].szVirtqName, i, pVirtio->virtqProxy[i].uAvailIdx,1274 i, pVirtio->virtq Proxy[i].uUsedIdx, i, pVirtio->uQueueSize[i],1315 i, pVirtio->virtqState[i].szVirtqName, i, pVirtio->virtqState[i].uAvailIdx, 1316 i, pVirtio->virtqState[i].uUsedIdx, i, pVirtio->uQueueSize[i], 1275 1317 i, pVirtio->uQueueNotifyOff[i],i, pVirtio->uQueueMsixVector[i], 1276 1318 i, pVirtio->uQueueEnable[i], i, pVirtio->pGcPhysQueueDesc[i], … … 1330 1372 rc = SSMR3PutU16(pSSM, pVirtio->uQueueEnable[i]); 1331 1373 rc = SSMR3PutU16(pSSM, pVirtio->uQueueSize[i]); 1332 rc = SSMR3PutU16(pSSM, pVirtio->virtq Proxy[i].uAvailIdx);1333 rc = SSMR3PutU16(pSSM, pVirtio->virtq Proxy[i].uUsedIdx);1334 rc = SSMR3PutMem(pSSM, pVirtio->virtq Proxy[i].szVirtqName, 32);1374 rc = SSMR3PutU16(pSSM, pVirtio->virtqState[i].uAvailIdx); 1375 rc = SSMR3PutU16(pSSM, pVirtio->virtqState[i].uUsedIdx); 1376 rc = SSMR3PutMem(pSSM, pVirtio->virtqState[i].szVirtqName, 32); 1335 1377 } 1336 1378 … … 1389 1431 rc = SSMR3GetU16(pSSM, &pVirtio->uQueueEnable[i]); 1390 1432 rc = SSMR3GetU16(pSSM, &pVirtio->uQueueSize[i]); 1391 rc = SSMR3GetU16(pSSM, &pVirtio->virtq Proxy[i].uAvailIdx);1392 rc = SSMR3GetU16(pSSM, &pVirtio->virtq Proxy[i].uUsedIdx);1393 rc = SSMR3GetMem(pSSM, (void *)&pVirtio->virtq Proxy[i].szVirtqName, 32);1433 rc = SSMR3GetU16(pSSM, &pVirtio->virtqState[i].uAvailIdx); 1434 rc = SSMR3GetU16(pSSM, &pVirtio->virtqState[i].uUsedIdx); 1435 rc = SSMR3GetMem(pSSM, (void *)&pVirtio->virtqState[i].szVirtqName, 32); 1394 1436 } 1395 1437 } -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h
r80683 r80762 38 38 #define VIRTQ_MAX_CNT 24 /**< Max queues we allow guest to create */ 39 39 #define VIRTIO_NOTIFY_OFFSET_MULTIPLIER 2 /**< VirtIO Notify Cap. MMIO config param */ 40 #define VIRTIOSCSI_REGION_MEM_IO 0 /**< BAR for MMIO (implementation specific) */ 41 #define VIRTIOSCSI_REGION_PORT_IO 1 /**< BAR for PORT I/O (impl specific) */ 42 #define VIRTIOSCSI_REGION_PCI_CAP 2 /**< BAR for VirtIO Cap. MMIO (impl specific) */ 40 #define VIRTIO_REGION_PCI_CAP 2 /**< BAR for VirtIO Cap. MMIO (impl specific) */ 43 41 44 42 #define VIRTIO_HEX_DUMP(logLevel, pv, cb, base, title) \ … … 47 45 virtioHexDump((pv), (cb), (base), (title)); \ 48 46 } while (0) 47 48 49 /** 50 * The following structure holds the pre-processed context of descriptor chain pulled from a virtio queue 51 * to conduct a transaction between the client of this virtio implementation and the guest VM's virtio driver. 52 * It contains the head index of the descriptor chain, the output data from the client that has been 53 * converted to a contiguous virtual memory and a physical memory scatter-gather buffer for use by by 54 * the virtio framework to complete the transaction in the final phase of round-trip processing. 55 * 56 * The client should not modify the contents of this buffer. The primary field of interest to the 57 * client is pVirtSrc, which contains the VirtIO "OUT" (to device) buffer from the guest. 58 * 59 * Typical use is, When the client (worker thread) detects available data on the queue, it pulls the 60 * next one of these descriptor chain structs off the queue using virtioQueueGet(), processes the 61 * virtual memory buffer pVirtSrc, produces result data to pass back to the guest driver and calls 62 * virtioQueuePut() to return the result data to the client. 63 */ 64 typedef struct VIRTIO_DESC_CHAIN 65 { 66 uint32_t uHeadIdx; /**< Head idx of associated desc chain */ 67 size_t cbVirtSrc; /**< Size of virt source buffer */ 68 void *pVirtSrc; /**< Virt mem buf holding out data from guest */ 69 size_t cbPhysDst; /**< Total size of dst buffer */ 70 PRTSGBUF pSgPhysDst; /**< Phys S/G buf to store result for guest */ 71 } VIRTIO_DESC_CHAIN_T, *PVIRTIO_DESC_CHAIN_T, **PPVIRTIO_DESC_CHAIN_T; 49 72 50 73 /** … … 155 178 int virtioQueueAttach(VIRTIOHANDLE hVirtio, uint16_t qIdx, const char *pcszName); 156 179 157 158 /**159 * Get the features VirtIO is running withnow.160 *161 * @returns Features the guest driver has accepted, finalizing the operational features162 *163 */164 uint64_t virtioGetNegotiatedFeatures(VIRTIOHANDLE hVirtio);165 166 180 /** 167 181 * Detaches from queue and release resources … … 174 188 175 189 /** 176 * Get name of queue, by qIdx, assigned at virtioQueueAttach() 177 * 178 * @param hVirtio - Handle for VirtIO framework 179 * @param qIdx - Queue number 180 * 181 * @returns Success: Returns pointer to queue name 182 * Failure: Returns "<null>" (never returns NULL pointer). 183 */ 184 const char *virtioQueueGetName(VIRTIOHANDLE hVirtio, uint16_t qIdx); 185 186 /** 187 * Removes descriptor chain from avail ring of indicated queue and converts it to 188 * scatter/gather buffer (whose segments contain guest phys. data pointers) 189 * 190 * @param hVirtio - Handle for VirtIO framework 191 * @param qIdx - Queue number 192 * @param ppInSegs - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF 193 * @param ppOutSegs - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF 194 * 195 * @returns status VINF_SUCCESS - Success 196 * VERR_INVALID_STATE - VirtIO not in ready state 197 */ 198 int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, bool fRemove, PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs); 199 200 /** 201 * Same as virtioQueueGet() but leaves the item on the avail ring of the queue. 202 * 203 * @param hVirtio - Handle for VirtIO framework 204 * @param qIdx - Queue number 205 * @param ppInSegs - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF 206 * @param ppOutSegs - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF 207 * 208 * @returns VINF_SUCCESS - Success 209 * VERR_INVALID_STATE - VirtIO not in ready state 210 * VERR_NOT_AVAILABLE - Queue is empty 211 */ 212 int virtioQueuePeek(VIRTIOHANDLE hVirtio, uint16_t qIdx, PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs); 213 214 /** 215 * Writes a scatter/gather buffer (whose segments point to virtual memory) to next 216 * available descriptor chain (consisting of segments pointing to guest phys. memory), 217 * for the indicated virtq. The data won't be seen by the guest until the next 218 * client call to virtioQueueSync(), which puts aforementioned descriptor 219 * chain's head index on the indicated virtq's used ring (see VirtIO 1.0 220 * specification, Section 2.4 "Virtqueues"). 221 * 222 * @param hVirtio - Handle for VirtIO framework 223 * @param qIdx - Queue number 224 * @param pSgBuf - Caller's sgbuf of one or more virtual memory segments 225 * to write to the queue. This is useful because some kinds 226 * of transactions involve variable length subcomponents 227 * whose size can only be known near the time of writing. 228 * @parame fFence - If set put up copy fence (memory barrier) after 229 * copying to guest phys. mem. 230 * 231 * @returns VINF_SUCCESS - Success 232 * VERR_INVALID_STATE - VirtIO not in ready state 233 * VERR_NOT_AVAILABLE - Queue is empty 234 */ 235 int virtioQueuePut(VIRTIOHANDLE hVirtio, uint16_t qIdx, PRTSGBUF pSgBuf, bool fFence); 190 * Removes descriptor chain from avail ring of indicated queue and converts the descriptor 191 * chain into its OUT (to device) and IN to guest components. Additionally it converts 192 * the OUT desc chain data to a contiguous virtual memory buffer for easy consumption 193 * by the caller. The caller must return the descriptor chain pointer via virtioQueuePut() 194 * and then call virtioQueueSync() at some point to return the data to the guest and 195 * complete the transaction. 196 * 197 * @param hVirtio - Handle for VirtIO framework 198 * @param qIdx - Queue number 199 * @param fRemove - flags whether to remove desc chain from queue (false = peek) 200 * @param ppDescChain - Address to store pointer to descriptor chain that contains the 201 * pre-processed transaction information pulled from the virtq. 202 * 203 * @returns status VINF_SUCCESS - Success 204 * VERR_INVALID_STATE - VirtIO not in ready state 205 */ 206 int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove); 207 208 209 /** 210 * Returns data to the guest to complete a transaction initiated by virtQueueGet(). 211 * The caller passes in a pointer to a scatter-gather buffer of virtual memory segments 212 * and a pointer to the descriptor chain context originally derived from the pulled 213 * queue entry, and this function will put write the virtual memory s/g buffer into the 214 * guest's physical memory free the descriptor chain. The caller handles the freeing 215 * (as needed) of the virtual memory buffer. 216 * 217 * NOTE: This does a write-ahead to the used ring of the guest's queue. 218 * The data written won't be seen by the guest until the next call to virtioQueueSync() 219 * 220 * 221 * @param hVirtio - Handle for VirtIO framework 222 * @param qIdx - Queue number 223 * 224 * @param pSgVirtReturn - Points toscatter-gather buffer of virtual memory segments 225 the caller is returning to the guest. 226 * 227 * @param pDescChain - This contains the context of the scatter-gather buffer 228 * originally pulled from the queue. 229 * 230 * @parame fFence - If true, put up copy fence (memory barrier) after 231 * copying to guest phys. mem. 232 * 233 * @returns VINF_SUCCESS - Success 234 * VERR_INVALID_STATE - VirtIO not in ready state 235 * VERR_NOT_AVAILABLE - Queue is empty 236 */ 237 238 int virtioQueuePut(VIRTIOHANDLE hVirtio, uint16_t qIdx, PRTSGBUF pSgVirtReturn, 239 PVIRTIO_DESC_CHAIN_T pDescChain, bool fFence); 240 236 241 237 242 /** … … 297 302 void virtioPropagateResumeNotification(VIRTIOHANDLE hVirtio); 298 303 304 /** 305 * Get name of queue, by qIdx, assigned at virtioQueueAttach() 306 * 307 * @param hVirtio - Handle for VirtIO framework 308 * @param qIdx - Queue number 309 * 310 * @returns Success: Returns pointer to queue name 311 * Failure: Returns "<null>" (never returns NULL pointer). 312 */ 313 const char *virtioQueueGetName(VIRTIOHANDLE hVirtio, uint16_t qIdx); 314 315 /** 316 * Get the features VirtIO is running withnow. 317 * 318 * @returns Features the guest driver has accepted, finalizing the operational features 319 * 320 */ 321 uint64_t virtioGetNegotiatedFeatures(VIRTIOHANDLE hVirtio); 299 322 300 323 -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h
r80718 r80762 85 85 86 86 /** 87 * IN/OUT Descriptor chains descriptor chain associated with one element of virtq avail ring represented88 * as respective arrays of SG segments.89 */90 typedef struct VIRTQ_DESC_CHAIN /**< Describes a single queue element */91 {92 RTSGSEG aSegsIn[VIRTQ_MAX_SIZE]; /**< List of segments to write to guest */93 RTSGSEG aSegsOut[VIRTQ_MAX_SIZE]; /**< List of segments read from guest */94 uint32_t uHeadIdx; /**< Index at head desc (source of seg arrays) */95 uint32_t cSegsIn; /**< Count of segments in aSegsIn[] */96 uint32_t cSegsOut; /**< Count of segments in aSegsOut[] */97 } VIRTQ_DESC_CHAIN_T, *PVIRTQ_DESC_CHAIN_T;98 99 /**100 87 * Local implementation's usage context of a queue (e.g. not part of VirtIO specification) 101 88 */ 102 typedef struct VIRTQ_PROXY 103 { 104 RTSGBUF inSgBuf; /**< host-to-guest buffers */ 105 RTSGBUF outSgBuf; /**< guest-to-host buffers */ 89 typedef struct VIRTQSTATE 90 { 106 91 const char szVirtqName[32]; /**< Dev-specific name of queue */ 107 92 uint16_t uAvailIdx; /**< Consumer's position in avail ring */ 108 93 uint16_t uUsedIdx; /**< Consumer's position in used ring */ 109 94 bool fEventThresholdReached; /**< Don't lose track while queueing ahead */ 110 PVIRTQ_DESC_CHAIN_T pDescChain; /**< Per-queue s/g data. */ 111 } VIRTQ_PROXY_T, *PVIRTQ_PROXY_T; 95 } VIRTQSTATE, *PVIRTQSTATE; 112 96 113 97 /** … … 191 175 uint8_t uConfigGeneration; /**< (MMIO) Device config sequencer HOST */ 192 176 193 VIRTQ _PROXY_T virtqProxy[VIRTQ_MAX_CNT]; /**< Local impl-specific queue context */177 VIRTQSTATE virtqState[VIRTQ_MAX_CNT]; /**< Local impl-specific queue context */ 194 178 VIRTIOCALLBACKS virtioCallbacks; /**< Callback vectors to client */ 195 179 … … 378 362 DECLINLINE(bool) virtqIsEmpty(PVIRTIOSTATE pVirtio, uint16_t qIdx) 379 363 { 380 return virtioReadAvailRingIdx(pVirtio, qIdx) == pVirtio->virtq Proxy[qIdx].uAvailIdx;364 return virtioReadAvailRingIdx(pVirtio, qIdx) == pVirtio->virtqState[qIdx].uAvailIdx; 381 365 } 382 366
Note:
See TracChangeset
for help on using the changeset viewer.