Changeset 83913 in vbox for trunk/src/VBox/Devices/VirtIO
- Timestamp:
- Apr 22, 2020 4:52:12 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 137452
- Location:
- trunk/src/VBox/Devices/VirtIO
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r83664 r83913 174 174 DECLINLINE(bool) virtqIsEmpty(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue) 175 175 { 176 uint16_t uAvailGuest = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue);177 bool fEmpty = uAvailGuest == pVirtio->virtqState[idxQueue].uAvailIdx;178 179 Log6Func(("%s : uAvailGuest=%u uAvailIdx=%u.(%s)\n",180 VIRTQNAME(pVirtio, idxQueue), uAvailGuest , pVirtio->virtqState[idxQueue].uAvailIdx,176 uint16_t uAvailGuestIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue); 177 bool fEmpty = uAvailGuestIdx == pVirtio->virtqState[idxQueue].uAvailIdx; 178 179 Log6Func(("%s idx=%u, shadow idx=%u (%s)\n", 180 VIRTQNAME(pVirtio, idxQueue), uAvailGuestIdx, pVirtio->virtqState[idxQueue].uAvailIdx, 181 181 fEmpty ? "Queue empty" : "Queue has available descriptors")); 182 182 return fEmpty; … … 266 266 } 267 267 268 #if 0 /* unused - *May* be used when VIRTIO_F_EVENT_IDX optional feature is implemented VirtIO 1.0, 2.4.9.2*/269 268 DECLINLINE(void) virtioWriteUsedAvailEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, uint32_t uAvailEventIdx) 270 269 { … … 275 274 &uAvailEventIdx, sizeof(uAvailEventIdx)); 276 275 } 277 #endif278 276 279 277 … … 390 388 } 391 389 390 size_t virtioCoreSgBufCalcTotalLength(PVIRTIOSGBUF pGcSgBuf) 391 { 392 size_t cb = 0; 393 unsigned i = pGcSgBuf->cSegs; 394 while (i-- > 0) 395 cb += pGcSgBuf->paSegs[i].cbSeg; 396 return cb; 397 } 398 392 399 #ifdef LOG_ENABLED 400 401 void virtioPrintFeatures(VIRTIOCORE *pVirtio) 402 { 403 #ifdef LOG_ENABLED 404 static struct 405 { 406 uint64_t fFeatureBit; 407 const char *pcszDesc; 408 } const s_aFeatures[] = 409 { 410 { VIRTIO_F_RING_INDIRECT_DESC, " RING_INDIRECT_DESC Driver can use descriptors with VIRTQ_DESC_F_INDIRECT flag set\n" }, 411 { VIRTIO_F_RING_EVENT_IDX, " RING_EVENT_IDX Enables use_event and avail_event fields described in 2.4.7, 2.4.8\n" }, 412 { VIRTIO_F_VERSION_1, " VERSION Used to detect legacy drivers.\n" }, 413 }; 414 415 #define MAXLINE 80 416 /* Display as a single buf to prevent interceding log messages */ 417 uint16_t cbBuf = RT_ELEMENTS(s_aFeatures) * 132; 418 char *pszBuf = (char *)RTMemAllocZ(cbBuf); 419 Assert(pszBuf); 420 char *cp = pszBuf; 421 for (unsigned i = 0; i < RT_ELEMENTS(s_aFeatures); ++i) 422 { 423 bool isOffered = pVirtio->uDeviceFeatures & s_aFeatures[i].fFeatureBit; 424 bool isNegotiated = pVirtio->uDriverFeatures & s_aFeatures[i].fFeatureBit; 425 cp += RTStrPrintf(cp, cbBuf - (cp - pszBuf), " %s %s %s", 426 isOffered ? "+" : "-", isNegotiated ? "x" : " ", s_aFeatures[i].pcszDesc); 427 } 428 Log3(("VirtIO Features Configuration\n\n" 429 " Offered Accepted Feature Description\n" 430 " ------- -------- ------- -----------\n" 431 "%s\n", pszBuf)); 432 RTMemFree(pszBuf); 433 434 #else /* !LOG_ENABLED */ 435 RT_NOREF3(pThis, fFeatures, pcszText); 436 #endif /* !LOG_ENABLED */ 437 } 438 393 439 394 440 /** … … 910 956 uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, idxQueue, pVirtq->uAvailIdx); 911 957 958 if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX) 959 virtioWriteUsedAvailEvent(pDevIns,pVirtio, idxQueue, pVirtq->uAvailIdx + 1); 960 912 961 if (fRemove) 913 962 pVirtq->uAvailIdx++; … … 961 1010 Assert(pDescChain->cRefs > 0); 962 1011 963 AssertMsgReturn(IS_DRIVER_OK(pVirtio) /*&& pVirtio->uQueueEnable[idxQueue]*/, 964 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 1012 AssertMsgReturn(IS_DRIVER_OK(pVirtio), ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 965 1013 966 1014 Log6Func(("Copying client data to %s, desc chain (head desc_idx %d)\n", … … 973 1021 if (pSgVirtReturn) 974 1022 { 1023 size_t cbTarget = virtioCoreSgBufCalcTotalLength(pSgPhysReturn); 975 1024 cbRemain = cbTotal = RTSgBufCalcTotalLength(pSgVirtReturn); 1025 AssertMsgReturn(cbTarget >= cbRemain, ("Not space to write data to phys memory"), VERR_BUFFER_OVERFLOW); 976 1026 virtioCoreSgBufReset(pSgPhysReturn); /* Reset ptr because req data may have already been written */ 977 1027 while (cbRemain) 978 1028 { 979 PVIRTIOSGSEG paSeg = &pSgPhysReturn->paSegs[pSgPhysReturn->idxSeg]; 980 /** @todo r=bird: Shouldn't this be: RT_MIN(pSgVirtReturn->cbSegLeft, pSgPhysReturn->cbSegLeft); */ 981 cbCopy = RT_MIN(pSgVirtReturn->cbSegLeft, paSeg->cbSeg - (size_t)(pSgPhysReturn->gcPhysCur - paSeg->gcPhys)); 982 Assert(cbCopy > 0); /** @todo r=bird: There is no check that there is sufficient space in the output 983 * buffer (pSgPhysReturn), so we might loop here forever if the caller is careless, 984 * right? I'm pretty sure virtioScsiR3SendEvent could do more checks. */ 1029 cbCopy = RT_MIN(pSgVirtReturn->cbSegLeft, pSgPhysReturn->cbSegLeft); 1030 Assert(cbCopy > 0); 985 1031 PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)pSgPhysReturn->gcPhysCur, pSgVirtReturn->pvSegCur, cbCopy); 986 1032 RTSgBufAdvance(pSgVirtReturn, cbCopy); … … 1030 1076 * @param pVirtio Pointer to the shared virtio state. 1031 1077 * @param idxQueue Queue number 1078 * @param fForce Force guest notification even if VIRTQ_USED_F_NO_NOTIFY is set 1032 1079 * 1033 1080 * @returns VBox status code. … … 1035 1082 * @retval VERR_INVALID_STATE VirtIO not in ready state 1036 1083 */ 1037 int virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue )1084 int virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fForce) 1038 1085 { 1039 1086 Assert(idxQueue < RT_ELEMENTS(pVirtio->virtqState)); … … 1047 1094 1048 1095 virtioWriteUsedRingIdx(pDevIns, pVirtio, idxQueue, pVirtq->uUsedIdx); 1049 virtioNotifyGuestDriver(pDevIns, pVirtio, idxQueue, f alse);1096 virtioNotifyGuestDriver(pDevIns, pVirtio, idxQueue, fForce); 1050 1097 1051 1098 return VINF_SUCCESS; … … 1101 1148 if (pVirtq->fEventThresholdReached) 1102 1149 { 1150 #ifdef IN_RING3 1151 Log6Func(("...kicking guest %s, VIRTIO_F_EVENT_IDX set and threshold (%d) reached\n", 1152 VIRTQNAME(pVirtio, idxQueue), (uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxQueue))); 1153 #else 1154 Log6Func(("... kicking guest %s, VIRTIO_F_EVENT_IDX set and threshold reached\n", 1155 VIRTQNAME(pVirtio, idxQueue))); 1156 #endif 1103 1157 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[idxQueue], fForce); 1104 1158 pVirtq->fEventThresholdReached = false; 1105 1159 return; 1106 1160 } 1107 Log6Func(("...skipping interrupt: VIRTIO_F_EVENT_IDX set but threshold not reached\n")); 1161 #ifdef IN_RING3 1162 Log6Func(("...skipping interrupt %s, VIRTIO_F_EVENT_IDX set but threshold (%d) not reached (%d)\n", 1163 VIRTQNAME(pVirtio, idxQueue),(uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxQueue), pVirtq->uUsedIdx)); 1164 #else 1165 Log6Func(("...skipping interrupt %s, VIRTIO_F_EVENT_IDX set but threshold not reached\n", 1166 VIRTQNAME(pVirtio, idxQueue))); 1167 #endif 1108 1168 } 1109 1169 else … … 1112 1172 if (fForce || !(virtioReadUsedRingFlags(pDevIns, pVirtio, idxQueue) & VIRTQ_AVAIL_F_NO_INTERRUPT)) 1113 1173 { 1174 if (fForce) 1175 Log6Func(("... kicking guest, queue %s, because force flag set\n")); 1114 1176 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[idxQueue], fForce); 1115 1177 return; 1116 1178 } 1117 /** TEMPORARY DEBUGGING HACK, EVALUATE AND REMOVE */ 1118 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[idxQueue], fForce); 1119 1120 Log6Func(("...skipping interrupt. Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n")); 1179 Log6Func(("...skipping interrupt, queue %s, Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n")); 1121 1180 } 1122 1181 } … … 1134 1193 { 1135 1194 if (fForce) 1136 Log6Func(("reason: resumed after suspend\n"));1195 Log6Func(("reason: forced\n")); 1137 1196 else 1138 1197 if (uCause == VIRTIO_ISR_VIRTQ_INTERRUPT) … … 1170 1229 { 1171 1230 Assert(idxQueue < RT_ELEMENTS(pVirtio->virtqState)); 1172 PVIRTQSTATE pVirtQ = &pVirtio->virtqState[idxQueue]; 1173 pVirtQ->uAvailIdx = 0; 1174 pVirtQ->uUsedIdx = 0; 1231 PVIRTQSTATE pVirtq = &pVirtio->virtqState[idxQueue]; 1232 pVirtq->uAvailIdx = 0; 1233 pVirtq->uUsedIdx = 0; 1234 pVirtq->fEventThresholdReached = false; 1175 1235 pVirtio->uQueueEnable[idxQueue] = false; 1176 1236 pVirtio->uQueueSize[idxQueue] = VIRTQ_MAX_SIZE; 1177 1237 pVirtio->uQueueNotifyOff[idxQueue] = idxQueue; 1178 1238 pVirtio->uQueueMsixVector[idxQueue] = idxQueue + 2; 1179 1180 1239 if (!pVirtio->fMsiSupport) /* VirtIO 1.0, 4.1.4.3 and 4.1.5.1.2 */ 1181 1240 pVirtio->uQueueMsixVector[idxQueue] = VIRTIO_MSI_NO_VECTOR; -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h
r83603 r83913 269 269 uint8_t uPrevDeviceStatus; /**< (MMIO) Prev Device Status GUEST */ 270 270 uint8_t uConfigGeneration; /**< (MMIO) Device config sequencer HOST */ 271 272 271 VIRTQSTATE virtqState[VIRTQ_MAX_CNT]; /**< Local impl-specific queue context */ 273 272 … … 281 280 /** @} */ 282 281 283 bool fGenUpdatePending; 282 bool fGenUpdatePending; /**< If set, update cfg gen after driver reads */ 284 283 uint8_t uPciCfgDataOff; 285 uint8_t uISR; 284 uint8_t uISR; /**< Interrupt Status Register. */ 286 285 uint8_t fMsiSupport; 287 286 … … 419 418 420 419 int virtioCoreR3QueuePendingCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue); 421 int virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue );420 int virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fForce); 422 421 bool virtioCoreQueueIsEmpty(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue); 423 422 void virtioCoreQueueEnable(PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fEnabled); … … 425 424 void virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio); 426 425 void virtioCoreResetAll(PVIRTIOCORE pVirtio); 426 void virtioPrintFeatures(VIRTIOCORE *pVirtio); 427 427 428 428 /** … … 474 474 return pVirtio->uDriverFeatures; 475 475 } 476 476 477 477 478 /** … … 503 504 size_t virtioCoreSgBufCalcTotalLength(PCVIRTIOSGBUF pGcSgBuf); 504 505 void virtioCoreSgBufReset(PVIRTIOSGBUF pGcSgBuf); 506 size_t virtioCoreSgBufCalcTotalLength(PVIRTIOSGBUF pGcSgBuf); 505 507 int virtioCoreR3SaveExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM); 506 508 int virtioCoreR3LoadExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM);
Note:
See TracChangeset
for help on using the changeset viewer.