Changeset 83566 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Apr 5, 2020 4:23:16 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r83565 r83566 33 33 #include <VBox/vmm/pdmstorageifs.h> 34 34 #include <VBox/vmm/pdmcritsect.h> 35 #include <VBox/AssertGuest.h> 35 36 #include <VBox/msi.h> 36 37 #include <VBox/version.h> … … 96 97 97 98 #define VIRTIOSCSI_SENSE_SIZE_DEFAULT 96 /**< VirtIO 1.0: 96 on reset, guest can change */ 99 #define VIRTIOSCSI_SENSE_SIZE_MAX 4096 /**< Picked out of thin air by bird. */ 98 100 #define VIRTIOSCSI_CDB_SIZE_DEFAULT 32 /**< VirtIO 1.0: 32 on reset, guest can change */ 101 #define VIRTIOSCSI_CDB_SIZE_MAX 255 /**< Picked out of thin air by bird. */ 99 102 #define VIRTIOSCSI_PI_BYTES_IN 1 /**< Value TBD (see section 5.6.6.1) */ 100 103 #define VIRTIOSCSI_PI_BYTES_OUT 1 /**< Value TBD (see section 5.6.6.1) */ … … 646 649 { 647 650 if (uCmd < 0x1f) 648 return 6;651 return RT_MIN(6, cbMax); 649 652 if (uCmd >= 0x20 && uCmd < 0x60) 650 return 10;653 return RT_MIN(10, cbMax); 651 654 if (uCmd >= 0x60 && uCmd < 0x80) 652 655 return cbMax; 653 656 if (uCmd >= 0x80 && uCmd < 0xa0) 654 return 16;657 return RT_MIN(16, cbMax); 655 658 if (uCmd >= 0xa0 && uCmd < 0xc0) 656 return 12;659 return RT_MIN(12, cbMax); 657 660 return cbMax; 658 661 } … … 1107 1110 1108 1111 /* 1112 * Validate configuration values we use here before we start. 1113 */ 1114 /** @todo Report these as errors to the guest or does the caller do that? */ 1115 uint32_t const cbCdb = pThis->virtioScsiConfig.uCdbSize; 1116 ASSERT_GUEST_LOGREL_MSG_RETURN(cbCdb <= VIRTIOSCSI_CDB_SIZE_MAX, ("cbCdb=%#x\n", cbCdb), VERR_OUT_OF_RANGE); 1117 uint32_t const cbSense = pThis->virtioScsiConfig.uSenseSize; 1118 ASSERT_GUEST_LOGREL_MSG_RETURN(cbSense <= VIRTIOSCSI_SENSE_SIZE_MAX, ("cbSense=%#x\n", cbSense), VERR_OUT_OF_RANGE); 1119 1120 /* 1109 1121 * Extract command header and CDB from guest physical memory 1122 * The max size is rather small here (19 + 255 = 274), so put 1123 * it on the stack. 1110 1124 */ 1111 size_t cbReqHdr = sizeof(REQ_CMD_HDR_T) + pThis->virtioScsiConfig.uCdbSize; 1112 1125 size_t const cbReqHdr = sizeof(REQ_CMD_HDR_T) + cbCdb; 1113 1126 AssertReturn(pDescChain->cbPhysSend >= cbReqHdr, VERR_INVALID_PARAMETER); 1114 1127 1115 PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)RTMemAllocZ(cbReqHdr); 1116 AssertReturn(pVirtqReq, VERR_NO_MEMORY); 1117 uint8_t *pb = (uint8_t *)pVirtqReq; 1118 for (size_t cb = RT_MIN(pDescChain->cbPhysSend, cbReqHdr); cb; ) 1119 { 1120 size_t cbSeg = cb; 1128 AssertCompile(VIRTIOSCSI_CDB_SIZE_MAX < 4096); 1129 union 1130 { 1131 /*VIRTIOSCSI_REQ_CMD_T ReqCmd; - not needed */ 1132 struct 1133 { 1134 REQ_CMD_HDR_T ReqHdr; 1135 uint8_t abCdb[VIRTIOSCSI_CDB_SIZE_MAX]; 1136 }; 1137 uint8_t ab[sizeof(REQ_CMD_HDR_T) + VIRTIOSCSI_CDB_SIZE_MAX]; 1138 uint64_t au64Align[(sizeof(REQ_CMD_HDR_T) + VIRTIOSCSI_CDB_SIZE_MAX) / sizeof(uint64_t)]; 1139 } VirtqReq; 1140 RT_ZERO(VirtqReq); 1141 1142 for (size_t offReq = 0; offReq < cbReqHdr; ) 1143 { 1144 size_t cbSeg = cbReqHdr - offReq; 1121 1145 RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg); 1122 PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pb, cbSeg); 1123 pb += cbSeg; 1124 cb -= cbSeg; 1125 } 1126 1127 uint8_t uType = pVirtqReq->ReqHdr.abVirtioLun[0]; 1128 uint8_t uTarget = pVirtqReq->ReqHdr.abVirtioLun[1]; 1129 uint32_t uScsiLun = (pVirtqReq->ReqHdr.abVirtioLun[2] << 8 | pVirtqReq->ReqHdr.abVirtioLun[3]) & 0x3fff; 1146 PDMDevHlpPCIPhysRead(pDevIns, GCPhys, &VirtqReq.ab[offReq], cbSeg); 1147 offReq += cbSeg; 1148 } 1149 1150 uint8_t const uType = VirtqReq.ReqHdr.abVirtioLun[0]; 1151 uint8_t const uTarget = VirtqReq.ReqHdr.abVirtioLun[1]; 1152 uint32_t uScsiLun = RT_MAKE_U16(VirtqReq.ReqHdr.abVirtioLun[3], VirtqReq.ReqHdr.abVirtioLun[2]) & 0x3fff; 1130 1153 1131 1154 bool fBadLUNFormat = false; … … 1145 1168 1146 1169 LogFunc(("[%s] (Target: %d LUN: %d) CDB: %.*Rhxs\n", 1147 SCSICmdText( pVirtqReq->uCdb[0]), uTarget, uScsiLun,1148 virtioScsiEstimateCdbLen( pVirtqReq->uCdb[0], pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb));1170 SCSICmdText(VirtqReq.abCdb[0]), uTarget, uScsiLun, 1171 virtioScsiEstimateCdbLen(VirtqReq.abCdb[0], cbCdb), &VirtqReq.abCdb[0])); 1149 1172 1150 1173 Log3Func(("cmd id: %RX64, attr: %x, prio: %d, crn: %x\n", 1151 pVirtqReq->ReqHdr.uId, pVirtqReq->ReqHdr.uTaskAttr, pVirtqReq->ReqHdr.uPrio, pVirtqReq->ReqHdr.uCrn));1174 VirtqReq.ReqHdr.uId, VirtqReq.ReqHdr.uTaskAttr, VirtqReq.ReqHdr.uPrio, VirtqReq.ReqHdr.uCrn)); 1152 1175 1153 1176 /* 1154 * Calculate request offsets 1177 * Calculate request offsets and data sizes. 1155 1178 */ 1156 off_t uDataOutOff = sizeof(REQ_CMD_HDR_T) + pThis->virtioScsiConfig.uCdbSize; 1157 off_t uDataInOff = sizeof(REQ_RESP_HDR_T) + pThis->virtioScsiConfig.uSenseSize; 1158 uint32_t cbDataOut = pDescChain->cbPhysSend - uDataOutOff; 1159 uint32_t cbDataIn = pDescChain->cbPhysReturn - uDataInOff; 1179 uint32_t const offDataOut = sizeof(REQ_CMD_HDR_T) + cbCdb; 1180 uint32_t const offDataIn = sizeof(REQ_RESP_HDR_T) + cbSense; 1181 uint32_t const cbDataOut = pDescChain->cbPhysSend - offDataOut; 1182 /** @todo r=bird: Validate cbPhysReturn properly? I've just RT_MAX'ed it for now. */ 1183 uint32_t const cbDataIn = RT_MAX(pDescChain->cbPhysReturn, offDataIn) - offDataIn; 1184 Assert(offDataOut <= UINT16_MAX); 1185 Assert(offDataIn <= UINT16_MAX); 1160 1186 1161 1187 /* … … 1173 1199 respHdr.uResidual = cbDataIn + cbDataOut; 1174 1200 virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, qIdx, pDescChain, &respHdr , NULL); 1175 RTMemFreeZ(pVirtqReq, cbReqHdr);1176 1201 return VINF_SUCCESS; 1177 1202 } … … 1193 1218 respHdr.uResidual = cbDataOut + cbDataIn; 1194 1219 virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, qIdx, pDescChain, &respHdr, abSense); 1195 RTMemFreeZ(pVirtqReq, cbReqHdr);1196 1220 return VINF_SUCCESS; 1197 1221 … … 1211 1235 respHdr.uResidual = cbDataOut + cbDataIn; 1212 1236 virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, qIdx, pDescChain, &respHdr, abSense); 1213 RTMemFreeZ(pVirtqReq, cbReqHdr);1214 1237 return VINF_SUCCESS; 1215 1238 } … … 1225 1248 respHdr.uResidual = cbDataIn + cbDataOut; 1226 1249 virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, qIdx, pDescChain, &respHdr, NULL); 1227 RTMemFreeZ(pVirtqReq, cbReqHdr);1228 1250 return VINF_SUCCESS; 1229 1251 } … … 1244 1266 respHdr.uResidual = cbDataIn + cbDataOut; 1245 1267 virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, qIdx, pDescChain, &respHdr , abSense); 1246 RTMemFreeZ(pVirtqReq, cbReqHdr);1247 1268 return VINF_SUCCESS; 1248 1269 } … … 1258 1279 PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR); 1259 1280 1260 if (RT_FAILURE(rc)) 1261 { 1262 RTMemFreeZ(pVirtqReq, cbReqHdr); 1263 AssertMsgRCReturn(rc, ("Failed to allocate I/O request, rc=%Rrc\n", rc), rc); 1264 } 1281 AssertMsgRCReturn(rc, ("Failed to allocate I/O request, rc=%Rrc\n", rc), rc); 1265 1282 1266 1283 pReq->hIoReq = hIoReq; … … 1270 1287 pReq->cbDataOut = cbDataOut; 1271 1288 pReq->pDescChain = pDescChain; 1272 pReq->uDataInOff = uDataInOff;1273 pReq->uDataOutOff = uDataOutOff;1274 1275 pReq->cbSenseAlloc = pThis->virtioScsiConfig.uSenseSize;1289 pReq->uDataInOff = offDataIn; 1290 pReq->uDataOutOff = offDataOut; 1291 1292 pReq->cbSenseAlloc = cbSense; 1276 1293 pReq->pbSense = (uint8_t *)RTMemAllocZ(pReq->cbSenseAlloc); 1277 1294 AssertMsgReturnStmt(pReq->pbSense, ("Out of memory allocating sense buffer"), 1278 virtioScsiR3FreeReq(pTarget, pReq); RTMemFreeZ(pVirtqReq, cbReqHdr);, VERR_NO_MEMORY);1295 virtioScsiR3FreeReq(pTarget, pReq);, VERR_NO_MEMORY); 1279 1296 1280 1297 /* Note: DrvSCSI allocates one virtual memory buffer for input and output phases of the request */ 1281 1298 rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, uScsiLun, 1282 pVirtqReq->uCdb, (size_t)pThis->virtioScsiConfig.uCdbSize,1299 &VirtqReq.abCdb[0], cbCdb, 1283 1300 PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, &pReq->enmTxDir, 1284 1301 RT_MAX(cbDataIn, cbDataOut), … … 1316 1333 } 1317 1334 1318 RTMemFreeZ(pVirtqReq, cbReqHdr);1319 1335 return VINF_SUCCESS; 1320 1336 }
Note:
See TracChangeset
for help on using the changeset viewer.