- Timestamp:
- Sep 6, 2019 4:24:53 AM (5 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r80596 r80615 108 108 109 109 #define IS_REQ_QUEUE(qIdx) (qIdx >= VIRTQ_REQ_BASE && qIdx < VIRTIOSCSI_QUEUE_CNT) 110 111 /** 112 * This macro resolves to boolean true if uOffset matches a field offset and size exactly, 113 * (or if it is a 64-bit field, if it accesses either 32-bit part as a 32-bit access) 114 * ASSUMED this critereon is mandated by section 4.1.3.1 of the VirtIO 1.0 specification) 115 * This MACRO can be re-written to allow unaligned access to a field (within bounds). 116 * 117 * @param member - Member of VIRTIO_PCI_COMMON_CFG_T 118 * @result - true or false 119 */ 120 #define MATCH_SCSI_CONFIG(member) \ 121 (RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \ 122 && ( uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \ 123 || uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \ 124 && cb == sizeof(uint32_t)) \ 125 || (uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \ 126 && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member)) 127 128 #define LOG_ACCESSOR(member) \ 129 virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \ 130 pv, cb, uIntraOffset, fWrite, false, 0); 131 132 #define SCSI_CONFIG_ACCESSOR(member) \ 133 { \ 134 uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \ 135 if (fWrite) \ 136 memcpy(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset, (const char *)pv, cb); \ 137 else \ 138 memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \ 139 LOG_ACCESSOR(member); \ 140 } 141 142 #define SCSI_CONFIG_ACCESSOR_READONLY(member) \ 143 { \ 144 uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \ 145 if (fWrite) \ 146 LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \ 147 else \ 148 { \ 149 memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \ 150 LOG_ACCESSOR(member); \ 151 } \ 152 } 153 154 #define VIRTIO_IN_DIRECTION(pMediaExTxDirEnumValue) \ 155 pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE 156 157 #define VIRTIO_OUT_DIRECTION(pMediaExTxDirEnumValue) \ 158 pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE 110 159 /** 111 160 * The following struct is the VirtIO SCSI Host Device device-specific configuration described in section 5.6.4 … … 493 542 494 543 #define SET_LUN_BUF(target, lun, out) \ 495 out[0] = 0x01; out[1] = target; out[2] = (lun >> 8) & 0x40; out[3] = lun & 0xff; *((uint16_t *)out + 4) = 0; 496 544 out[0] = 0x01; \ 545 out[1] = target; \ 546 out[2] = (lun >> 8) & 0x40; \ 547 out[3] = lun & 0xff; \ 548 *((uint16_t *)out + 4) = 0; 497 549 498 550 DECLINLINE(bool) isBufZero(uint8_t *pv, size_t cb) … … 595 647 } 596 648 597 /**598 * This macro resolves to boolean true if uOffset matches a field offset and size exactly,599 * (or if it is a 64-bit field, if it accesses either 32-bit part as a 32-bit access)600 * ASSUMED this critereon is mandated by section 4.1.3.1 of the VirtIO 1.0 specification)601 * This MACRO can be re-written to allow unaligned access to a field (within bounds).602 *603 * @param member - Member of VIRTIO_PCI_COMMON_CFG_T604 * @result - true or false605 */606 #define MATCH_SCSI_CONFIG(member) \607 (RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \608 && ( uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \609 || uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \610 && cb == sizeof(uint32_t)) \611 || (uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \612 && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member))613 614 #define LOG_ACCESSOR(member) \615 virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \616 pv, cb, uIntraOffset, fWrite, false, 0);617 618 #define SCSI_CONFIG_ACCESSOR(member) \619 { \620 uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \621 if (fWrite) \622 memcpy(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset, (const char *)pv, cb); \623 else \624 memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \625 LOG_ACCESSOR(member); \626 }627 628 #define SCSI_CONFIG_ACCESSOR_READONLY(member) \629 { \630 uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \631 if (fWrite) \632 LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \633 else \634 { \635 memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \636 LOG_ACCESSOR(member); \637 } \638 }639 640 #define VIRTIO_IN_DIRECTION(pMediaExTxDirEnumValue) \641 pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE642 643 #define VIRTIO_OUT_DIRECTION(pMediaExTxDirEnumValue) \644 pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE645 646 649 typedef struct VIRTIOSCSIREQ *PVIRTIOSCSIREQ; 647 650 … … 667 670 } 668 671 #endif 672 673 DECLINLINE(void) virtioScsiVirtToSgPhys(PVIRTIOSCSI pThis, PRTSGBUF pSgDst, void *pvSrc, size_t cb) 674 { 675 while (cb) 676 { 677 size_t cbSeg = cb; 678 RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pSgDst, &cbSeg); 679 PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSrc, cbSeg); 680 pvSrc = ((uint8_t *)pvSrc) + cbSeg; 681 cb -= cbSeg; 682 } 683 } 684 685 DECLINLINE(void) virtioScsiSgPhysTogVirt(PVIRTIOSCSI pThis, PRTSGBUF pSgSrc, void *pvDst, size_t cb) 686 { 687 while (cb) 688 { 689 size_t cbSeg = cb; 690 RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pSgSrc, &cbSeg); 691 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvDst, cbSeg); 692 pvDst = ((uint8_t *)pvDst) + cbSeg; 693 cb -= cbSeg; 694 } 695 } 669 696 670 697 /** … … 701 728 */ 702 729 static DECLCALLBACK(int) virtioScsiR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 703 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, 704 size_t cbCopy) 705 { 706 RT_NOREF(hIoReq); 707 RT_NOREF(pInterface); 708 730 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, size_t cbCopy) 731 { 732 RT_NOREF2(hIoReq, pInterface); 709 733 PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc; 710 711 /** DrvSCSI.cpp, that issues this callback, just sticks one segment in the buffer */ 712 memcpy(pReq->pbDataIn + offDst, pSgBuf->paSegs[0].pvSeg, cbCopy); 734 if (pReq->pbDataIn) 735 RTSgBufCopyToBuf(pSgBuf, pReq->pbDataIn + offDst, cbCopy); 713 736 return VINF_SUCCESS; 714 737 } 715 738 716 717 739 /** 718 740 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf} 719 741 */ 720 742 static DECLCALLBACK(int) virtioScsiR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 721 void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, 722 size_t cbCopy) 723 { 724 RT_NOREF(hIoReq); 725 RT_NOREF(pInterface); 726 743 void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, size_t cbCopy) 744 { 745 RT_NOREF2(hIoReq, pInterface); 727 746 PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc; 728 /** DrvSCSI.cpp, that issues this callback, just sticks one segment in the buffer */ 729 730 memcpy(pSgBuf->paSegs[0].pvSeg, pReq->pbDataOut + offSrc, cbCopy); 747 if (pReq->pbDataOut) 748 RTSgBufCopyFromBuf(pSgBuf, pReq->pbDataOut + offSrc, cbCopy); 731 749 732 750 return VINF_SUCCESS; … … 799 817 } 800 818 819 static void virtioScsiFreeReq(PVIRTIOSCSITARGET pTarget, PVIRTIOSCSIREQ pReq) 820 { 821 RTMemFree(pReq->pbSense); 822 RTMemFree(pReq->pbPiIn); 823 RTMemFree(pReq->pbDataIn); 824 RTMemFree(pReq->pVirtqReq); 825 pTarget->pDrvMediaEx->pfnIoReqFree(pTarget->pDrvMediaEx, pReq->hIoReq); 826 } 827 801 828 /** 802 829 * This is called to complete a request immediately … … 848 875 * and return the failure code for any-and-all until that's done before 849 876 * allowing a reset to continue. 850 *851 * In the absence of active I/O farmed out to VSCSI852 * the device handles a guest driver unload/reload gracefully and has853 * been tested.854 877 */ 855 878 static int virtioScsiReqFinish(PVIRTIOSCSI pThis, PVIRTIOSCSIREQ pReq, int rcReq) … … 1012 1035 1013 1036 Log(("-----------------------------------------------------------------------------------------\n")); 1014 1015 } 1016 RTMemFree(pReq->pbSense); 1017 RTMemFree(pReq->pbDataIn); 1018 RTMemFree(pReq->pbPiIn); 1019 RTMemFree(pReq->pVirtqReq); 1020 1021 pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq); 1037 } 1038 1039 virtioScsiFreeReq(pTarget, pReq); 1022 1040 1023 1041 if (pTarget->cReqsInProgress == 0 && pThis->fSignalIdle) … … 1026 1044 return VINF_SUCCESS; 1027 1045 } 1046 1028 1047 1029 1048 static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PRTSGBUF pInSgBuf, PRTSGBUF pOutSgBuf) … … 1038 1057 AssertReturn(pVirtqReq, VERR_NO_MEMORY); 1039 1058 1040 off_t cbOff = 0; 1041 size_t cbCopy = cbOut; 1042 while (cbCopy) 1043 { 1044 size_t cbSeg = cbCopy; 1045 RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pOutSgBuf, &cbSeg); 1046 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, ((uint8_t *)pVirtqReq) + cbOff, cbSeg); 1047 cbCopy -= cbSeg; 1048 cbOff += cbSeg; 1049 } 1050 1051 // VIRTIO_HEX_DUMP(RTLOGGRPFLAGS_LEVEL_12, (uint8_t *)pVirtqReq, cbOut, 0, "\npVirtqReq"); 1059 virtioScsiSgPhysTogVirt(pThis, pOutSgBuf, pVirtqReq, cbOut); 1052 1060 1053 1061 uint8_t uTarget = pVirtqReq->cmdHdr.uLUN[1]; … … 1093 1101 respHdr.uResidual = cbDataOut + cbDataIn; 1094 1102 virtioScsiReqErr(pThis, qIdx, &respHdr, abSense); 1103 RTMemFree(pVirtqReq); 1095 1104 return VINF_SUCCESS; 1096 1105 } … … 1136 1145 pReq->cbIn = cbIn; 1137 1146 pReq->cbOut = cbOut; 1138 pReq->pbDataOut = pbDataOut;1139 1147 pReq->cbDataOut = cbDataOut; 1148 pReq->pbDataOut = cbDataOut ? pbDataOut : 0; 1140 1149 pReq->pVirtqReq = pVirtqReq; 1141 1150 pReq->pInSgBuf = pInSgBuf; … … 1155 1164 rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, uLUN, 1156 1165 pVirtqReq->uCdb, pThis->virtioScsiConfig.uCdbSize, 1157 PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, &pReq->enmTxDir, cbDataIn, 1166 PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, &pReq->enmTxDir, 1167 RT_MAX(cbDataIn, cbDataOut), 1158 1168 pReq->pbSense, pReq->cbSense, &pReq->uSenseLen, 1159 1169 &pReq->uStatus, 30 * RT_MS_1SEC); … … 1188 1198 respHdr.uResidual = cbDataIn + cbDataOut; 1189 1199 virtioScsiReqErr(pThis, qIdx, &respHdr, abSense); 1190 RTMemFree(pReq->pbSense); 1191 RTMemFree(pReq->pbDataIn); 1192 RTMemFree(pReq->pbPiIn); 1193 RTMemFree(pVirtqReq); 1194 pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq); 1200 virtioScsiFreeReq(pTarget, pReq); 1195 1201 return VINF_SUCCESS; 1196 1202 } … … 1213 1219 static int virtioScsiCtrl(PVIRTIOSCSI pThis, uint16_t qIdx, PRTSGBUF pInSgBuf, PRTSGBUF pOutSgBuf) 1214 1220 { 1215 RT_NOREF(pThis); 1216 RT_NOREF(qIdx); 1217 RT_NOREF(pInSgBuf); 1221 RT_NOREF3(pThis, qIdx, pInSgBuf); 1218 1222 1219 1223 /** … … 1227 1231 AssertMsgReturn(pScsiCtrl, ("Out of memory"), VERR_NO_MEMORY); 1228 1232 1229 /** 1230 * Get control command into virtual memory 1231 */ 1232 off_t cbOff = 0; 1233 size_t cbSeg = 0; 1234 while (cbOut) 1235 { 1236 RTGCPHYS pvSeg = (RTGCPHYS)RTSgBufGetNextSegment(pOutSgBuf, &cbSeg); 1237 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pvSeg, pScsiCtrl + cbOff, cbSeg); 1238 cbOut -= cbSeg; 1239 cbOff += cbSeg; 1240 } 1233 virtioScsiSgPhysTogVirt(pThis, pOutSgBuf, pScsiCtrl, cbOut); 1241 1234 1242 1235 uint8_t uResponse = VIRTIOSCSI_S_OK; … … 1414 1407 if (rc == VERR_NOT_AVAILABLE) 1415 1408 { 1416 Log 3Func(("Nothing found in %s\n", QUEUENAME(qIdx)));1409 Log6Func(("Nothing found in %s\n", QUEUENAME(qIdx))); 1417 1410 continue; 1418 1411 } -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r80596 r80615 1463 1463 1464 1464 /** 1465 * Do a hex dump of a buffer .1465 * Do a hex dump of a buffer 1466 1466 * 1467 1467 * @param pv Pointer to array to dump … … 1475 1475 if (pszTitle) 1476 1476 Log(("%s [%d bytes]:\n", pszTitle, cb)); 1477 for (uint32_t row = 0; row < RT_MAX(1, (cb / 16) + 1) ; row++)1477 for (uint32_t row = 0; row < RT_MAX(1, (cb / 16) + 1) && row * 16 < cb; row++) 1478 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++) 1479 Log(("%04x: ", row * 16 + uBase)); /* line address */ 1480 for (uint8_t col = 0; col < 16; col++) 1482 1481 { 1483 1482 uint32_t idx = row * 16 + col; 1484 uint8_t u8 = pv[idx];1485 1483 if (idx >= cb) 1486 1484 Log(("-- %s", (col + 1) % 8 ? "" : " ")); 1487 1485 else 1488 Log(("% x%x %s", u8 >> 4 & 0xf, u8 & 0xf, (col + 1) % 8 ? "" : " "));1486 Log(("%02x %s", pv[idx], (col + 1) % 8 ? "" : " ")); 1489 1487 } 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 } 1488 for (uint32_t idx = row * 16; idx < row * 16 + 16; idx++) 1489 Log(("%c", (idx >= cb) ? ' ' : (pv[idx] >= 0x20 && pv[idx] <= 0x7e ? pv[idx] : '.'))); 1499 1490 Log(("\n")); 1500 1491 }
Note:
See TracChangeset
for help on using the changeset viewer.