Changeset 80383 in vbox for trunk/src/VBox/Devices/VirtIO
- Timestamp:
- Aug 22, 2019 7:25:38 AM (5 years ago)
- Location:
- trunk/src/VBox/Devices/VirtIO
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r80340 r80383 28 28 #include <iprt/mem.h> 29 29 #include <iprt/assert.h> 30 #include <iprt/sg.h> 30 31 #include <VBox/vmm/pdmdev.h> 31 32 #include "Virtio_1_0_impl.h" … … 35 36 36 37 #ifdef LOG_ENABLED 37 # define QUEUENAME(s, q) (q->sz Name)38 # define QUEUENAME(s, q) (q->szVirtqName) 38 39 #endif 39 40 … … 93 94 } 94 95 96 /** 97 * See API comments in header file for description 98 */ 95 99 int virtioQueueAttach(VIRTIOHANDLE hVirtio, uint16_t qIdx, const char *pcszName) 96 100 { … … 98 102 PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio; 99 103 PVIRTQ_PROXY_T pVirtqProxy = &(pVirtio->virtqProxy[qIdx]); 100 if (pVirtio->uQueueEnable[qIdx]) 101 { 102 pVirtqProxy->pBufVec = (PVIRTQ_BUF_VECTOR_T)RTMemAllocZ(sizeof(PVIRTQ_BUF_VECTOR_T)); 103 if (!pVirtqProxy->pBufVec) 104 { 105 Log(("Out of memory!")); 106 return VERR_NO_MEMORY; 107 } 108 pVirtqProxy->uAvailIdx = 0; 109 pVirtqProxy->uUsedIdx = 0; 110 pVirtqProxy->fEventThresholdReached = false; 111 RTStrCopy((char *)pVirtqProxy->szName, sizeof(pVirtqProxy->szName), pcszName); 112 return VINF_SUCCESS; 113 } 114 LogFunc(("Couldn't attach to %s: Not enabled\n", pcszName)); 115 return VERR_INVALID_STATE; 116 } 117 118 PVIRTQ_BUF_VECTOR_T virtioQueueGetBuffer(VIRTIOHANDLE hVirtio, uint16_t qIdx) 119 { 120 PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio; 121 if (pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK) 122 { 123 PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx]; 124 return pVirtqProxy->pBufVec; 125 } 126 LogFunc(("Can't get buffer, driver not ready\n")); 127 return NULL; 128 } 129 104 pVirtqProxy->pDescChain = (PVIRTQ_DESC_CHAIN_T)RTMemAllocZ(sizeof(VIRTQ_DESC_CHAIN_T)); 105 if (!pVirtqProxy->pDescChain) 106 { 107 Log(("Out of memory!")); 108 return VERR_NO_MEMORY; 109 } 110 pVirtqProxy->uAvailIdx = 0; 111 pVirtqProxy->uUsedIdx = 0; 112 pVirtqProxy->fEventThresholdReached = false; 113 RTStrCopy((char *)pVirtqProxy->szVirtqName, sizeof(pVirtqProxy->szVirtqName), pcszName); 114 return VINF_SUCCESS; 115 116 } 117 118 /** 119 * See API comments in header file for description 120 */ 130 121 const char *virtioQueueGetName(VIRTIOHANDLE hVirtio, uint16_t qIdx) 131 122 { … … 134 125 ("Guest driver not in ready state.\n"), "<null>"); 135 126 136 return (const char *)((PVIRTIOSTATE)hVirtio)->virtqProxy[qIdx].szName; 137 } 138 127 return (const char *)((PVIRTIOSTATE)hVirtio)->virtqProxy[qIdx].szVirtqName; 128 } 129 130 /** 131 * See API comments in header file for description 132 */ 139 133 int virtioQueueSkip(VIRTIOHANDLE hVirtio, uint16_t qIdx) 140 134 { … … 150 144 return VERR_NOT_AVAILABLE; 151 145 152 Log2Func(("%s: %s avail_idx=%u\n", INSTANCE(pVirtio), 153 pVirtqProxy->szName, pVirtqProxy->uAvailIdx)); 146 Log2Func(("%s avail_idx=%u\n", pVirtqProxy->szVirtqName, pVirtqProxy->uAvailIdx)); 154 147 pVirtqProxy->uAvailIdx++; 155 148 … … 157 150 } 158 151 152 153 /** 154 * See API comments in header file for description 155 */ 156 uint64_t virtioGetNegotiatedFeatures(VIRTIOHANDLE hVirtio) 157 { 158 PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio; 159 return pVirtio->uDriverFeatures; 160 } 161 162 163 /** 164 * See API comments in header file for description 165 */ 159 166 bool virtioQueueIsEmpty(VIRTIOHANDLE hVirtio, uint16_t qIdx) 160 167 { … … 163 170 } 164 171 165 int virtioQueuePeek(VIRTIOHANDLE hVirtio, uint16_t qIdx) 166 { 167 return virtioQueueGet(hVirtio, qIdx, false /* fRemove */); 168 } 169 170 /** See API comments in header file prototype for description */ 171 int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, bool fRemove) 172 /** 173 * See API comments in header file for description 174 */ 175 int virtioQueuePeek(VIRTIOHANDLE hVirtio, uint16_t qIdx, PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs) 176 { 177 return virtioQueueGet(hVirtio, qIdx, false /* fRemove */, ppInSegs, ppOutSegs); 178 } 179 180 /*/** 181 * See API comments in header file for description 182 */ 183 int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, bool fRemove, 184 PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs) 172 185 { 173 186 PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio; 174 187 PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx]; 175 PVIRTQ_ BUF_VECTOR_T pBufVec = pVirtqProxy->pBufVec;188 PVIRTQ_DESC_CHAIN_T pDescChain = pVirtqProxy->pDescChain; 176 189 177 190 AssertMsgReturn(DRIVER_OK(pVirtio) && pVirtio->uQueueEnable[qIdx], … … 181 194 return VERR_NOT_AVAILABLE; 182 195 183 pBufVec->cSegsIn = pBufVec->cSegsOut = 0; 184 185 Log2Func(("%s avail_idx=%u\n", INSTANCE(pVirtio), pVirtqProxy->szName, pVirtqProxy->uAvailIdx)); 186 187 uint16_t uDescIdx; 188 // pBufVec->uDescIdx = uDescIdx = vqReadAvailRingDescIdx(pVirtio, qIdx, pVirtqProxy->uAvailIdx); 196 pDescChain->cSegsIn = pDescChain->cSegsOut = 0; 197 198 199 pDescChain->uHeadIdx = vqReadAvailRingDescIdx(pVirtio, qIdx, pVirtqProxy->uAvailIdx); 200 uint16_t uDescIdx = pDescChain->uHeadIdx; 201 202 Log2Func(("%s DESC CHAIN: (head) desc_idx=%u [avail_idx=%u]\n", 203 pVirtqProxy->szVirtqName, pDescChain->uHeadIdx, pVirtqProxy->uAvailIdx)); 189 204 190 205 if (fRemove) … … 194 209 do 195 210 { 196 VIRTQ_SEG_T*pSeg;211 RTSGSEG *pSeg; 197 212 198 213 /** … … 202 217 * the following aborts I/O if breach and employs a simple log throttling algorithm to notify. 203 218 */ 204 if (p BufVec->cSegsIn + pBufVec->cSegsOut >= VIRTQ_MAX_SIZE)219 if (pDescChain->cSegsIn + pDescChain->cSegsOut >= VIRTQ_MAX_SIZE) 205 220 { 206 221 static volatile uint32_t s_cMessages = 0; … … 208 223 if (ASMAtomicIncU32(&s_cMessages) == ASMAtomicReadU32(&s_cThreshold)) 209 224 { 210 LogRel(("%s: too many linked descriptors; " 211 "check if the guest arranges descriptors in a loop.\n", 212 INSTANCE(pVirtio))); 225 LogRel(("too many linked descriptors; " 226 "check if the guest arranges descriptors in a loop.\n")); 213 227 if (ASMAtomicReadU32(&s_cMessages) != 1) 214 LogRel((" %s:(the above error has occured %u times so far)\n",215 INSTANCE(pVirtio),ASMAtomicReadU32(&s_cMessages)));228 LogRel(("(the above error has occured %u times so far)\n", 229 ASMAtomicReadU32(&s_cMessages))); 216 230 ASMAtomicWriteU32(&s_cThreshold, ASMAtomicReadU32(&s_cThreshold) * 10); 217 231 } … … 220 234 RT_UNTRUSTED_VALIDATED_FENCE(); 221 235 222 // vqReadDesc(pVirtio, qIdx, uDescIdx, &desc); 236 vqReadDesc(pVirtio, qIdx, uDescIdx, &desc); 237 223 238 if (desc.fFlags & VIRTQ_DESC_F_WRITE) 224 239 { 225 Log2Func(("%s: %s IN seg=%u desc_idx=%u addr=%RTp cb=%u\n", INSTANCE(pVirtio), 226 pVirtqProxy->szName, pBufVec->cSegsIn, uDescIdx, desc.pGcPhysBuf, desc.cb)); 227 pSeg = &(pBufVec->aSegsIn[pBufVec->cSegsIn++]); 240 Log2Func(("%*s IN desc_idx=%u seg=%u addr=%RGp cb=%u\n", 241 RTStrNLen(pVirtqProxy->szVirtqName, sizeof(pVirtqProxy->szVirtqName)), "", 242 uDescIdx, pDescChain->cSegsIn, desc.pGcPhysBuf, desc.cb)); 243 244 pSeg = &(pDescChain->aSegsIn[pDescChain->cSegsIn++]); 228 245 } 229 246 else 230 247 { 231 Log2Func(("% s: %s IN seg=%u desc_idx=%u addr=%RTp cb=%u\n", INSTANCE(pVirtio),232 pVirtqProxy->szName, pBufVec->cSegsOut, uDescIdx, desc.pGcPhysBuf, desc.cb));233 pSeg = &(pBufVec->aSegsOut[pBufVec->cSegsOut++]);234 }235 236 pSeg->addr = (RTGCPHYS)desc.pGcPhysBuf; 237 pSeg-> cb = desc.cb;238 pSeg-> pv = NULL;248 Log2Func(("%*s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n", 249 RTStrNLen(pVirtqProxy->szVirtqName, sizeof(pVirtqProxy->szVirtqName)), "", 250 uDescIdx, pDescChain->cSegsOut, desc.pGcPhysBuf, desc.cb)); 251 pSeg = &(pDescChain->aSegsOut[pDescChain->cSegsOut++]); 252 } 253 254 pSeg->pvSeg = (void *)desc.pGcPhysBuf; 255 pSeg->cbSeg = desc.cb; 239 256 240 257 uDescIdx = desc.uDescIdxNext; 241 258 } while (desc.fFlags & VIRTQ_DESC_F_NEXT); 242 259 243 Log2Func(("%s: %s head_desc_idx=%u nIn=%u nOut=%u\n", INSTANCE(pVirtio), 244 pVirtqProxy->szName, pBufVec->uDescIdx, pBufVec->cSegsIn, pBufVec->cSegsOut)); 260 RTSgBufInit(&pVirtqProxy->inSgBuf, (PCRTSGSEG)&pDescChain->aSegsIn, pDescChain->cSegsIn); 261 RTSgBufInit(&pVirtqProxy->outSgBuf,(PCRTSGSEG)&pDescChain->aSegsOut, pDescChain->cSegsOut); 262 263 *ppInSegs = &pVirtqProxy->inSgBuf; 264 *ppOutSegs = &pVirtqProxy->outSgBuf; 265 266 Log2Func(("%*s -- segs out: %u, segs in: %u --\n", 267 RTStrNLen(pVirtqProxy->szVirtqName, sizeof(pVirtqProxy->szVirtqName)), "", 268 pDescChain->cSegsOut, pDescChain->cSegsIn)); 245 269 246 270 return VINF_SUCCESS; … … 254 278 PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio; 255 279 PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx]; 256 PVIRTQ_ BUF_VECTOR_T pBufVec = pVirtqProxy->pBufVec;280 PVIRTQ_DESC_CHAIN_T pDescChain = pVirtqProxy->pDescChain; 257 281 258 282 AssertMsgReturn(DRIVER_OK(pVirtio) && pVirtio->uQueueEnable[qIdx], 259 283 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 260 284 261 Log2Func(("%s : %sdesc_idx=%u acb=%u\n",262 INSTANCE(pVirtio), pVirtqProxy->szName, pBufVec->uDescIdx, pBufVec->cSegsIn));263 264 uint32_t cbRemaining = p BufVec->cSegsIn;265 266 for (uint32_t iSeg = 0; iSeg < p BufVec->cSegsIn && cbRemaining > 0; ++iSeg)267 { 268 uint32_t cbSegLen = p BufVec->aSegsIn[iSeg].cb;285 Log2Func(("%s desc_idx=%u acb=%u\n", 286 pVirtqProxy->szVirtqName, pDescChain->uHeadIdx, pDescChain->cSegsIn)); 287 288 uint32_t cbRemaining = pDescChain->cSegsIn; 289 290 for (uint32_t iSeg = 0; iSeg < pDescChain->cSegsIn && cbRemaining > 0; ++iSeg) 291 { 292 uint32_t cbSegLen = pDescChain->aSegsIn[iSeg].cbSeg; 269 293 if (cbSegLen > cbRemaining) // last segment only partially used? 270 294 cbSegLen = cbRemaining; 271 295 272 273 if (pBufVec->aSegsIn[iSeg].pv != NULL) 274 { 275 Log2Func(("%s: %s used_idx=%u seg=%u addr=%p pv=%p cb=%u acb=%u\n", 276 INSTANCE(pVirtio), pVirtqProxy->szName, 277 pVirtqProxy->uUsedIdx, iSeg, 278 (void *)pBufVec->aSegsIn[iSeg].addr, pBufVec->aSegsIn[iSeg].pv, 279 pBufVec->aSegsIn[iSeg].cb, cbSegLen)); 280 281 PDMDevHlpPCIPhysWrite(pVirtio->CTX_SUFF(pDevIns), 282 pBufVec->aSegsIn[iSeg].addr, pBufVec->aSegsIn[iSeg].pv, cbSegLen); 283 } 296 // if (pDescChain->aSegsIn[iSeg].pv != NULL) 297 // { 298 // Log2Func(("%s used_idx=%u seg=%u addr=%p cb=%u acb=%u\n", 299 // pVirtqProxy->szVirtqName, 300 // pVirtqProxy->uUsedIdx, iSeg, 301 // (void *)pDescChain->aSegsIn[iSeg].addr, 302 // pDescChain->aSegsIn[iSeg].cbSeg, cbSegLen)); 303 // 304 // PDMDevHlpPCIPhysWrite(pVirtio->CTX_SUFF(pDevIns), 305 // pDescChain->aSegsIn[iSeg].pvSeg, pDescChain->aSegsIn[iSeg].pv, cbSegLen); 306 // } 284 307 cbRemaining -= cbSegLen; 285 308 } 286 309 287 310 uint16_t uDescIdx = vqReadUsedDescIdx(pVirtio, qIdx); 288 Log2Func(("%s : %sused_idx=%u guest_used_idx=%u id=%u len=%u\n",289 INSTANCE(pVirtio), pVirtqProxy->szName,290 pVirtqProxy->uUsedIdx, uDescIdx, p BufVec->uDescIdx, pBufVec->cSegsIn));311 Log2Func(("%s used_idx=%u guest_used_idx=%u id=%u len=%u\n", 312 pVirtqProxy->szVirtqName, 313 pVirtqProxy->uUsedIdx, uDescIdx, pDescChain->uHeadIdx, pDescChain->cSegsIn)); 291 314 292 315 if (pVirtqProxy->uUsedIdx == vqReadAvailUsedEvent(pVirtio, qIdx)) 293 316 pVirtqProxy->fEventThresholdReached = true; 294 vqWriteUsedElem(pVirtio, qIdx, pVirtqProxy->uUsedIdx++, p BufVec->uDescIdx, pBufVec->cSegsIn);317 vqWriteUsedElem(pVirtio, qIdx, pVirtqProxy->uUsedIdx++, pDescChain->uHeadIdx, pDescChain->cSegsIn); 295 318 296 319 return VINF_SUCCESS; 297 320 } 298 321 299 /** See API comments in header file prototype for description */ 322 /** 323 * See API comments in header file for description 324 */ 300 325 int virtioQueueSync(VIRTIOHANDLE hVirtio, uint16_t qIdx) 301 326 { … … 309 334 310 335 uint16_t uDescIdx = vqReadUsedDescIdx(pVirtio, qIdx); 311 Log2Func(("%s : %sold_used_idx=%u new_used_idx=%u\n",312 INSTANCE(pVirtio),uDescIdx, pVirtqProxy->uUsedIdx));336 Log2Func(("%s old_used_idx=%u new_used_idx=%u\n", 337 uDescIdx, pVirtqProxy->uUsedIdx)); 313 338 314 339 vqWriteUsedRingDescIdx(pVirtio, qIdx, pVirtqProxy->uUsedIdx); … … 318 343 } 319 344 320 /** See API comments in header file prototype for description */ 345 /** 346 * See API comments in header file for description 347 */ 321 348 static void virtioQueueNotified(PVIRTIOSTATE pVirtio, uint16_t qIdx, uint16_t uNotifyIdx) 322 349 { … … 324 351 325 352 PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx]; 326 Log2Func(("%s : %s notified\n", INSTANCE(pVirtio), pVirtqProxy->szName));353 Log2Func(("%s\n", pVirtqProxy->szVirtqName)); 327 354 328 355 /** Inform client */ … … 343 370 ("Guest driver not in ready state.\n")); 344 371 345 LogFlowFunc(("%s : %savailFlags=%x guestFeatures=%x virtioQueue is %sempty\n",346 INSTANCE(pVirtio), pVirtqProxy->szName, vqReadAvailFlags(pVirtio, qIdx),372 LogFlowFunc(("%s availFlags=%x guestFeatures=%x virtioQueue is %sempty\n", 373 pVirtqProxy->szVirtqName, vqReadAvailFlags(pVirtio, qIdx), 347 374 pVirtio->uDriverFeatures, vqIsEmpty(pVirtio, qIdx) ? "" : "not ")); 348 375 … … 390 417 RT_NOREF(offDelta); 391 418 PVIRTIOSTATE pVirtio = *PDMINS_2_DATA(pDevIns, PVIRTIOSTATE *); 392 LogFunc((" %s\n", INSTANCE(pVirtio)));419 LogFunc(("\n")); 393 420 394 421 pVirtio->pDevInsR3 = pDevIns; … … 406 433 { 407 434 if (uCause == VIRTIO_ISR_VIRTQ_INTERRUPT) 408 LogFlowFunc((" %s: Cause: queue interrupt\n", INSTANCE(pVirtio)));435 LogFlowFunc(("Cause: queue interrupt\n")); 409 436 else 410 437 if (uCause == VIRTIO_ISR_DEVICE_CONFIG) 411 LogFlowFunc((" %s: Cause: device config\n", INSTANCE(pVirtio)));438 LogFlowFunc(("Cause: device config\n")); 412 439 413 440 pVirtio->uISR |= uCause; … … 423 450 static void virtioLowerInterrupt(PVIRTIOSTATE pVirtio) 424 451 { 425 LogFlowFunc((" %s\n", INSTANCE(pVirtio)));452 LogFlowFunc(("\n")); 426 453 PDMDevHlpPCISetIrq(pVirtio->CTX_SUFF(pDevIns), 0, 0); 427 454 } … … 713 740 { 714 741 ++pVirtio->uConfigGeneration; 715 Log2Func(("Bumped cfg. generation to %d because %s 742 Log2Func(("Bumped cfg. generation to %d because %s%s\n", 716 743 pVirtio->uConfigGeneration, 717 744 fDevSpecificFieldChanged ? "<dev cfg changed> " : "", … … 1024 1051 pVirtio->pDevSpecificCfg = pDevSpecificCfg; 1025 1052 1026 pVirtio->pPrevDevSpecificCfg = RTMemAlloc (cbDevSpecificCfg);1053 pVirtio->pPrevDevSpecificCfg = RTMemAllocZ(cbDevSpecificCfg); 1027 1054 if (!pVirtio->pPrevDevSpecificCfg) 1028 1055 { … … 1131 1158 * VirtIO 1.0 spec says 8-bit, unaligned in MMIO space. Example/diagram 1132 1159 * of spec shows it as a 32-bit field with upper bits 'reserved' 1133 * Will take spec words very literally for now and check linux driver.1160 * Will take spec words more literally than the diagram for now. 1134 1161 */ 1135 1162 pCfg = (PVIRTIO_PCI_CAP_T)&pVirtio->dev.abConfig[pCfg->uCapNext]; … … 1201 1228 * out size, so pad with an extra page */ 1202 1229 1203 rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIOSCSI_REGION_PCI_CAP, RT_ALIGN_32(cbRegion + 4096, 4096),1230 rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIOSCSI_REGION_PCI_CAP, RT_ALIGN_32(cbRegion + 0x1000, 0x1000), 1204 1231 PCI_ADDRESS_SPACE_MEM, virtioR3Map); 1205 1232 if (RT_FAILURE(rc)) … … 1253 1280 { 1254 1281 Log2Func(("%s queue:\n", 1255 " virtqProxy[%u].uAvailIdx = %u\n virtqProxy[%u].uUsedIdx = %u\n"1282 " virtqProxy[%u].uAvailIdx = %u\n virtqProxy[%u].uUsedIdx = %u\n" 1256 1283 " uQueueSize[%u] = %u\n uQueueNotifyOff[%u] = %04x\n" 1257 1284 " uQueueMsixVector[%u] = %04x\n uQueueEnable[%u] = %04x\n" 1258 1285 " pGcPhysQueueDesc[%u] = %RGp\n pGcPhysQueueAvail[%u] = %RGp\n" 1259 1286 " pGcPhysQueueUsed[%u] = %RGp\n", 1260 i, pVirtio->virtqProxy[i].sz Name, i, pVirtio->virtqProxy[i].uAvailIdx,1287 i, pVirtio->virtqProxy[i].szVirtqName, i, pVirtio->virtqProxy[i].uAvailIdx, 1261 1288 i, pVirtio->virtqProxy[i].uUsedIdx, i, pVirtio->uQueueSize[i], 1262 1289 i, pVirtio->uQueueNotifyOff[i],i, pVirtio->uQueueMsixVector[i], … … 1319 1346 rc = SSMR3PutU16(pSSM, pVirtio->virtqProxy[i].uAvailIdx); 1320 1347 rc = SSMR3PutU16(pSSM, pVirtio->virtqProxy[i].uUsedIdx); 1321 rc = SSMR3PutMem(pSSM, pVirtio->virtqProxy[i].sz Name, 32);1348 rc = SSMR3PutMem(pSSM, pVirtio->virtqProxy[i].szVirtqName, 32); 1322 1349 } 1323 1350 … … 1378 1405 rc = SSMR3GetU16(pSSM, &pVirtio->virtqProxy[i].uAvailIdx); 1379 1406 rc = SSMR3GetU16(pSSM, &pVirtio->virtqProxy[i].uUsedIdx); 1380 rc = SSMR3GetMem(pSSM, (void *)&pVirtio->virtqProxy[i].sz Name, 32);1407 rc = SSMR3GetMem(pSSM, (void *)&pVirtio->virtqProxy[i].szVirtqName, 32); 1381 1408 } 1382 1409 } -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h
r80340 r80383 23 23 24 24 #include <iprt/ctype.h> 25 #include <iprt/sg.h> 25 26 26 27 typedef void * VIRTIOHANDLE; /**< Opaque handle to the VirtIO framework */ 27 28 28 #define DISABLE_GUEST_DRIVER 029 29 30 30 /** … … 37 37 #define VIRTQ_MAX_SIZE 1024 /**< Max size (# desc elements) of a virtq */ 38 38 #define VIRTQ_MAX_CNT 24 /**< Max queues we allow guest to create */ 39 #define VIRTQ_DESC_MAX_SIZE (2 * 1024 * 1024) 39 40 40 #define VIRTIO_NOTIFY_OFFSET_MULTIPLIER 2 /**< VirtIO Notify Cap. MMIO config param */ 41 41 #define VIRTIOSCSI_REGION_MEM_IO 0 /**< BAR for MMIO (implementation specific) */ 42 42 #define VIRTIOSCSI_REGION_PORT_IO 1 /**< BAR for PORT I/O (impl specific) */ 43 43 #define VIRTIOSCSI_REGION_PCI_CAP 2 /**< BAR for VirtIO Cap. MMIO (impl specific) */ 44 typedef struct VIRTQ_SEG /**< Describes one segment of a buffer vector */45 {46 RTGCPHYS addr; /**< Physical addr. of this segment's buffer */47 void *pv; /**< Buf to hold value to write or read */48 uint32_t cb; /**< Number of bytes to write or read */49 } VIRTQ_SEG_T;50 51 typedef struct VIRTQ_BUF_VECTOR /**< Scatter/gather buffer vector */52 {53 uint32_t uDescIdx; /**< Desc at head of this vector list */54 uint32_t cSegsIn; /**< Count of segments in aSegsIn[] */55 uint32_t cSegsOut; /**< Count of segments in aSegsOut[] */56 VIRTQ_SEG_T aSegsIn[VIRTQ_MAX_SIZE]; /**< List of segments to write to guest */57 VIRTQ_SEG_T aSegsOut[VIRTQ_MAX_SIZE]; /**< List of segments read from guest */58 } VIRTQ_BUF_VECTOR_T, *PVIRTQ_BUF_VECTOR_T;59 44 60 45 /** … … 72 57 uint16_t uRevisionId; /**< PCI Cfg Revision ID */ 73 58 uint16_t uInterruptLine; /**< PCI Cfg Interrupt line */ 74 uint16_t uInterruptPin; /**< PCI Cfg Interrupt Pin*/59 uint16_t uInterruptPin; /**< PCI Cfg Interrupt pin */ 75 60 } VIRTIOPCIPARAMS, *PVIRTIOPCIPARAMS; 76 61 … … 151 136 * Allocate client context for client to work with VirtIO-provided with queue 152 137 * As a side effect creates a buffer vector a client can get a pointer to 153 * with a call to virtioQueue BufVec()138 * with a call to virtioQueueDescChain() 154 139 * 155 140 * @param hVirtio - Handle to VirtIO framework … … 164 149 */ 165 150 int virtioQueueAttach(VIRTIOHANDLE hVirtio, uint16_t qIdx, const char *pcszName); 151 152 153 /** 154 * Get the features VirtIO is running withnow. 155 * 156 * @returns Features the guest driver has accepted, finalizing the operational features 157 * 158 */ 159 uint64_t virtioGetNegotiatedFeatures(VIRTIOHANDLE hVirtio); 160 166 161 /** 167 162 * Detaches from queue and release resources … … 172 167 */ 173 168 int virtioQueueDetach(VIRTIOHANDLE hVirtio, uint16_t qIdx); 174 175 /**176 * Return pointer to buffer vector object associated with queue177 *178 * @param hVirtio - Handle for VirtIO framework179 * @param qIdx - Queue number180 *181 * @returns Pointer pBufVec if success, else NULL182 */183 PVIRTQ_BUF_VECTOR_T virtioQueueGetBuffer(VIRTIOHANDLE hVirtio, uint16_t qIdx);184 169 185 170 /** … … 200 185 * @param hVirtio - Handle for VirtIO framework 201 186 * @param qIdx - Queue number 187 * @param ppInSegs - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF 188 * @param ppOutSegs - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF 202 189 * 203 190 * @returns status VINF_SUCCESS - Success 204 191 * VERR_INVALID_STATE - VirtIO not in ready state 205 192 */ 206 int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, bool fRemove );193 int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, bool fRemove, PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs); 207 194 208 195 /** … … 211 198 * @param hVirtio - Handle for VirtIO framework 212 199 * @param qIdx - Queue number 200 * @param ppInSegs - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF 201 * @param ppOutSegs - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF 213 202 * 214 203 * @returns VINF_SUCCESS - Success … … 216 205 * VERR_NOT_AVAILABLE - Queue is empty 217 206 */ 218 int virtioQueuePeek(VIRTIOHANDLE hVirtio, uint16_t qIdx );207 int virtioQueuePeek(VIRTIOHANDLE hVirtio, uint16_t qIdx, PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs); 219 208 220 209 /** -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h
r80340 r80383 59 59 #define VIRTIO_STATUS_DEVICE_NEEDS_RESET 0x40 /**< Device experienced unrecoverable error */ 60 60 61 /* @def Virtio Device PCI Capabilities type codes */61 /** @def Virtio Device PCI Capabilities type codes */ 62 62 #define VIRTIO_PCI_CAP_COMMON_CFG 1 /**< Common configuration PCI capability ID */ 63 63 #define VIRTIO_PCI_CAP_NOTIFY_CFG 2 /**< Notification area PCI capability ID */ … … 85 85 86 86 /** 87 * Translation of the descriptor chain associated with one element of virtq avail ring into its 88 * IN and OUT components and represented 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 /** 87 100 * Local implementation's usage context of a queue (e.g. not part of VirtIO specification) 88 101 */ 89 102 typedef struct VIRTQ_PROXY 90 103 { 91 const char szName[32]; /**< Dev-specific name of queue */ 92 PVIRTQ_BUF_VECTOR_T pBufVec; /**< Per-queue s/g data. Serialize access! */ 93 uint16_t uAvailIdx; /**< Consumer's position in avail ring */ 94 uint16_t uUsedIdx; /**< Consumer's position in used ring */ 95 bool fEventThresholdReached; /**< Don't lose track while queueing ahead */ 104 RTSGBUF inSgBuf; /**< host-to-guest buffers */ 105 RTSGBUF outSgBuf; /**< guest-to-host buffers */ 106 const char szVirtqName[32]; /**< Dev-specific name of queue */ 107 uint16_t uAvailIdx; /**< Consumer's position in avail ring */ 108 uint16_t uUsedIdx; /**< Consumer's position in used ring */ 109 bool fEventThresholdReached; /**< Don't lose track while queueing ahead */ 110 PVIRTQ_DESC_CHAIN_T pDescChain; /**< Per-queue s/g data. */ 96 111 } VIRTQ_PROXY_T, *PVIRTQ_PROXY_T; 97 112 … … 107 122 uint32_t uDeviceFeatures; /**< RO (device reports features to driver) */ 108 123 uint32_t uDriverFeaturesSelect; /**< RW (driver selects driver features) */ 109 uint32_t uDriverFeatures; /**< RW (driver accepts device features)*/124 uint32_t uDriverFeatures; /**< RW (driver-accepted device features) */ 110 125 uint16_t uMsixConfig; /**< RW (driver sets MSI-X config vector) */ 111 126 uint16_t uNumQueues; /**< RO (device specifies max queues) */ 112 uint8_t uDeviceStatus; /**< RW (driver writes device status, 0 resets)*/127 uint8_t uDeviceStatus; /**< RW (driver writes device status, 0=reset) */ 113 128 uint8_t uConfigGeneration; /**< RO (device changes when changing configs) */ 114 129 … … 136 151 } VIRTIO_PCI_CFG_CAP_T, *PVIRTIO_PCI_CFG_CAP_T; 137 152 138 139 153 /** 140 154 * The core (/common) state of the VirtIO PCI device … … 146 160 PDMPCIDEV dev; /**< PCI device */ 147 161 char szInstance[16]; /**< Instance name, e.g. "VIRTIOSCSI0" */ 148 void * pClientContext; 162 void * pClientContext; /**< Client callback returned on callbacks */ 149 163 150 164 PPDMDEVINSR3 pDevInsR3; /**< Device instance - R3 */ … … 177 191 uint8_t uConfigGeneration; /**< (MMIO) Device config sequencer HOST */ 178 192 179 VIRTQ_PROXY_T virtqProxy[VIRTQ_MAX_CNT]; /**< Local impl-specific queue context */193 VIRTQ_PROXY_T virtqProxy[VIRTQ_MAX_CNT]; /**< Local impl-specific queue context */ 180 194 VIRTIOCALLBACKS virtioCallbacks; /**< Callback vectors to client */ 181 195 … … 223 237 uint16_t uDescIdx; /**< idx Index of next free ring slot */ 224 238 uint16_t auRing[1]; /**< ring Ring: avail drv to dev bufs */ 225 uint16_t uUsedEventIdx; /**< used_event (if VIRTQ_USED_F_ NO_NOTIFY) */239 uint16_t uUsedEventIdx; /**< used_event (if VIRTQ_USED_F_EVENT_IDX) */ 226 240 } VIRTQ_AVAIL_T, *PVIRTQ_AVAIL_T; 227 241 … … 237 251 uint16_t uDescIdx; /**< idx Index of next ring slot */ 238 252 VIRTQ_USED_ELEM_T auRing[1]; /**< ring Ring: used dev to drv bufs */ 239 uint16_t uAvailEventIdx; /**< avail_event if (VIRTQ_USED_F_ NO_NOTIFY) */253 uint16_t uAvailEventIdx; /**< avail_event if (VIRTQ_USED_F_EVENT_IDX) */ 240 254 } VIRTQ_USED_T, *PVIRTQ_USED_T; 241 255 … … 335 349 */ 336 350 337 static int vqIsEventNeeded (uint16_t uEventIdx, uint16_t uDescIdxNew, uint16_t uDescIdxOld);351 static int vqIsEventNeeded (uint16_t uEventIdx, uint16_t uDescIdxNew, uint16_t uDescIdxOld); 338 352 static bool vqIsEmpty (PVIRTIOSTATE pVirtio, uint16_t qIdx); 339 353 static void vqReadDesc (PVIRTIOSTATE pVirtio, uint16_t qIdx, uint32_t uDescIdx, PVIRTQ_DESC_T pDesc); … … 361 375 362 376 /** 363 * Accessor for virtq desc spVirtio377 * Accessor for virtq descriptor 364 378 */ 365 379 DECLINLINE(void) vqReadDesc(PVIRTIOSTATE pVirtio, uint16_t qIdx, uint32_t uDescIdx, PVIRTQ_DESC_T pDesc)
Note:
See TracChangeset
for help on using the changeset viewer.