- Timestamp:
- Jul 13, 2020 7:37:06 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 139268
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp
r85109 r85291 1498 1498 if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED) 1499 1499 { 1500 LogFunc(("W aken due to %s\n", rc == VERR_TIMEOUT ? "timeout" : "getting interrupted"));1500 LogFunc(("Woken due to %s\n", rc == VERR_TIMEOUT ? "timeout" : "getting interrupted")); 1501 1501 continue; 1502 1502 } … … 1752 1752 paVirtSegsToGuest[cSegs].pvSeg = ((uint8_t *)pvBuf) + uOffset; 1753 1753 cbBufRemaining -= cbLimited; 1754 uOffset 1754 uOffset += cbLimited; 1755 1755 cVirtqBufs++; 1756 1756 cSegs++; … … 1923 1923 1924 1924 PVIRTIONETVIRTQ pRxVirtq = &pThis->aVirtqs[RXQIDX(uVirtqPair)]; 1925 if (RT_SUCCESS( !virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pRxVirtq)))1925 if (RT_SUCCESS(virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pRxVirtq))) 1926 1926 { 1927 /* Drop packets if VM is not running or cable is disconnected. */1928 if (!virtioNetIsOperational(pThis, pDevIns) || !IS_LINK_UP(pThis))1929 return VINF_SUCCESS;1930 1931 1927 STAM_PROFILE_START(&pThis->StatReceive, a); 1932 1928 virtioNetR3SetReadLed(pThisCC, true); -
trunk/src/VBox/Devices/VirtIO/VirtioCore.cpp
r85132 r85291 324 324 return virtioCoreVirtqAvailBufCount_inline(pDevIns, pVirtio, pVirtq); 325 325 } 326 327 /** @} */328 329 void virtioCoreGCPhysChainInit(PVIRTIOSGBUF pGcSgBuf, PVIRTIOSGSEG paSegs, size_t cSegs)330 {331 AssertPtr(pGcSgBuf);332 Assert( (cSegs > 0 && VALID_PTR(paSegs)) || (!cSegs && !paSegs));333 Assert(cSegs < (~(unsigned)0 >> 1));334 335 pGcSgBuf->paSegs = paSegs;336 pGcSgBuf->cSegs = (unsigned)cSegs;337 pGcSgBuf->idxSeg = 0;338 if (cSegs && paSegs)339 {340 pGcSgBuf->GCPhysCur = paSegs[0].GCPhys;341 pGcSgBuf->cbSegLeft = paSegs[0].cbSeg;342 }343 else344 {345 pGcSgBuf->GCPhysCur = 0;346 pGcSgBuf->cbSegLeft = 0;347 }348 }349 350 static RTGCPHYS virtioCoreGCPhysChainGet(PVIRTIOSGBUF pGcSgBuf, size_t *pcbData)351 {352 size_t cbData;353 RTGCPHYS pGcBuf;354 355 /* Check that the S/G buffer has memory left. */356 if (RT_LIKELY(pGcSgBuf->idxSeg < pGcSgBuf->cSegs && pGcSgBuf->cbSegLeft))357 { /* likely */ }358 else359 {360 *pcbData = 0;361 return 0;362 }363 364 AssertMsg( pGcSgBuf->cbSegLeft <= 128 * _1M365 && (RTGCPHYS)pGcSgBuf->GCPhysCur >= (RTGCPHYS)pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys366 && (RTGCPHYS)pGcSgBuf->GCPhysCur + pGcSgBuf->cbSegLeft <=367 (RTGCPHYS)pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys + pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg,368 ("pGcSgBuf->idxSeg=%d pGcSgBuf->cSegs=%d pGcSgBuf->GCPhysCur=%p pGcSgBuf->cbSegLeft=%zd "369 "pGcSgBuf->paSegs[%d].GCPhys=%p pGcSgBuf->paSegs[%d].cbSeg=%zd\n",370 pGcSgBuf->idxSeg, pGcSgBuf->cSegs, pGcSgBuf->GCPhysCur, pGcSgBuf->cbSegLeft,371 pGcSgBuf->idxSeg, pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys, pGcSgBuf->idxSeg,372 pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg));373 374 cbData = RT_MIN(*pcbData, pGcSgBuf->cbSegLeft);375 pGcBuf = pGcSgBuf->GCPhysCur;376 pGcSgBuf->cbSegLeft -= cbData;377 if (!pGcSgBuf->cbSegLeft)378 {379 pGcSgBuf->idxSeg++;380 381 if (pGcSgBuf->idxSeg < pGcSgBuf->cSegs)382 {383 pGcSgBuf->GCPhysCur = pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys;384 pGcSgBuf->cbSegLeft = pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg;385 }386 *pcbData = cbData;387 }388 else389 pGcSgBuf->GCPhysCur = pGcSgBuf->GCPhysCur + cbData;390 391 return pGcBuf;392 }393 394 void virtioCoreGCPhysChainReset(PVIRTIOSGBUF pGcSgBuf)395 {396 AssertPtrReturnVoid(pGcSgBuf);397 398 pGcSgBuf->idxSeg = 0;399 if (pGcSgBuf->cSegs)400 {401 pGcSgBuf->GCPhysCur = pGcSgBuf->paSegs[0].GCPhys;402 pGcSgBuf->cbSegLeft = pGcSgBuf->paSegs[0].cbSeg;403 }404 else405 {406 pGcSgBuf->GCPhysCur = 0;407 pGcSgBuf->cbSegLeft = 0;408 }409 }410 411 RTGCPHYS virtioCoreGCPhysChainAdvance(PVIRTIOSGBUF pGcSgBuf, size_t cbAdvance)412 {413 AssertReturn(pGcSgBuf, 0);414 415 size_t cbLeft = cbAdvance;416 while (cbLeft)417 {418 size_t cbThisAdvance = cbLeft;419 virtioCoreGCPhysChainGet(pGcSgBuf, &cbThisAdvance);420 if (!cbThisAdvance)421 break;422 423 cbLeft -= cbThisAdvance;424 }425 return cbAdvance - cbLeft;426 }427 428 RTGCPHYS virtioCoreGCPhysChainGetNextSeg(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg)429 {430 AssertReturn(pGcSgBuf, 0);431 AssertPtrReturn(pcbSeg, 0);432 433 if (!*pcbSeg)434 *pcbSeg = pGcSgBuf->cbSegLeft;435 436 return virtioCoreGCPhysChainGet(pGcSgBuf, pcbSeg);437 }438 439 size_t virtioCoreGCPhysChainCalcBufSize(PVIRTIOSGBUF pGcSgBuf)440 {441 size_t cb = 0;442 unsigned i = pGcSgBuf->cSegs;443 while (i-- > 0)444 cb += pGcSgBuf->paSegs[i].cbSeg;445 return cb;446 }447 326 448 327 #ifdef IN_RING3 … … 763 642 764 643 /** API Function: See header file */ 644 uint32_t virtioCoreR3VirtqBufRetain(PVIRTQBUF pVirtqBuf) 645 { 646 AssertReturn(pVirtqBuf, UINT32_MAX); 647 AssertReturn(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC, UINT32_MAX); 648 uint32_t cRefs = ASMAtomicIncU32(&pVirtqBuf->cRefs); 649 Assert(cRefs > 1); 650 Assert(cRefs < 16); 651 return cRefs; 652 } 653 654 655 /** API Function: See header file */ 656 uint32_t virtioCoreR3VirtqBufRelease(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf) 657 { 658 if (!pVirtqBuf) 659 return 0; 660 AssertReturn(pVirtqBuf, 0); 661 AssertReturn(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC, 0); 662 uint32_t cRefs = ASMAtomicDecU32(&pVirtqBuf->cRefs); 663 Assert(cRefs < 16); 664 if (cRefs == 0) 665 { 666 pVirtqBuf->u32Magic = ~VIRTQBUF_MAGIC; 667 RTMemFree(pVirtqBuf); 668 STAM_REL_COUNTER_INC(&pVirtio->StatDescChainsFreed); 669 } 670 return cRefs; 671 } 672 673 /** API Function: See header file */ 674 void virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio) 675 { 676 virtioKick(pVirtio->pDevInsR3, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig); 677 } 678 679 /** API Function: See header file */ 680 void virtioCoreVirtqEnableNotify(PVIRTIOCORE pVirtio, uint16_t uVirtq, bool fEnable) 681 { 682 683 Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues)); 684 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 685 686 if (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK) 687 { 688 uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, pVirtq); 689 690 if (fEnable) 691 fFlags &= ~ VIRTQ_USED_F_NO_NOTIFY; 692 else 693 fFlags |= VIRTQ_USED_F_NO_NOTIFY; 694 695 virtioWriteUsedRingFlags(pVirtio->pDevInsR3, pVirtio, pVirtq, fFlags); 696 } 697 } 698 699 /** API function: See Header file */ 700 void virtioCoreResetAll(PVIRTIOCORE pVirtio) 701 { 702 LogFunc(("\n")); 703 pVirtio->fDeviceStatus |= VIRTIO_STATUS_DEVICE_NEEDS_RESET; 704 if (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK) 705 { 706 pVirtio->fGenUpdatePending = true; 707 virtioKick(pVirtio->pDevInsR3, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig); 708 } 709 } 710 711 /** API function: See Header file */ 712 int virtioCoreR3VirtqAvailBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq, 713 PPVIRTQBUF ppVirtqBuf) 714 { 715 return virtioCoreR3VirtqAvailBufGet(pDevIns, pVirtio, uVirtq, ppVirtqBuf, false); 716 } 717 718 /** API function: See Header file */ 719 int virtioCoreR3VirtqAvailBufNext(PVIRTIOCORE pVirtio, uint16_t uVirtq) 720 { 721 Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues)); 722 723 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 724 725 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtq->uEnable, 726 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 727 728 if (IS_VIRTQ_EMPTY(pVirtio->pDevInsR3, pVirtio, pVirtq)) 729 return VERR_NOT_AVAILABLE; 730 731 Log6Func(("%s avail shadow idx: %u\n", pVirtq->szName, pVirtq->uAvailIdxShadow)); 732 pVirtq->uAvailIdxShadow++; 733 734 return VINF_SUCCESS; 735 } 736 737 738 /** API Function: See header file */ 765 739 int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq, 766 740 uint16_t uHeadIdx, PPVIRTQBUF ppVirtqBuf) … … 771 745 AssertMsgReturn(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues), 772 746 ("uVirtq out of range"), VERR_INVALID_PARAMETER); 747 773 748 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 774 775 if (!IS_DRIVER_OK(pVirtio) || !pVirtq->uEnable)776 {777 LogRelFunc(("Driver not ready or queue not enabled\n"));778 return 0;779 }780 749 781 750 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtq->uEnable, … … 784 753 uint16_t uDescIdx = uHeadIdx; 785 754 786 Log6Func(("%s DESC CHAIN: (head) desc_idx=%u\n", pVirt q->szName, uHeadIdx));755 Log6Func(("%s DESC CHAIN: (head) desc_idx=%u\n", pVirtio->aVirtqueues[uVirtq].szName, uHeadIdx)); 787 756 788 757 /* … … 794 763 pVirtqBuf->cRefs = 1; 795 764 pVirtqBuf->uHeadIdx = uHeadIdx; 796 pVirtqBuf->uVirtq = uVirtq;765 pVirtqBuf->uVirtq = uVirtq; 797 766 *ppVirtqBuf = pVirtqBuf; 798 767 … … 802 771 VIRTQ_DESC_T desc; 803 772 804 uint32_t cbIn = 0;805 uint32_t cbOut = 0;806 uint32_t cSegsIn = 0;773 uint32_t cbIn = 0; 774 uint32_t cbOut = 0; 775 uint32_t cSegsIn = 0; 807 776 uint32_t cSegsOut = 0; 777 808 778 PVIRTIOSGSEG paSegsIn = pVirtqBuf->aSegsIn; 809 779 PVIRTIOSGSEG paSegsOut = pVirtqBuf->aSegsOut; … … 847 817 cbOut += desc.cb; 848 818 pSeg = &paSegsOut[cSegsOut++]; 819 #ifdef DEEP_DEBUG 849 820 if (LogIs11Enabled()) 850 821 { … … 852 823 Log(("\n")); 853 824 } 825 #endif 854 826 } 855 827 … … 886 858 } 887 859 888 /** API Function: See header file */889 uint32_t virtioCoreR3VirtqBufRetain(PVIRTQBUF pVirtqBuf)890 {891 AssertReturn(pVirtqBuf, UINT32_MAX);892 AssertReturn(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC, UINT32_MAX);893 uint32_t cRefs = ASMAtomicIncU32(&pVirtqBuf->cRefs);894 Assert(cRefs > 1);895 Assert(cRefs < 16);896 return cRefs;897 }898 899 900 /** API Function: See header file */901 uint32_t virtioCoreR3VirtqBufRelease(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf)902 {903 if (!pVirtqBuf)904 return 0;905 AssertReturn(pVirtqBuf, 0);906 AssertReturn(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC, 0);907 uint32_t cRefs = ASMAtomicDecU32(&pVirtqBuf->cRefs);908 Assert(cRefs < 16);909 if (cRefs == 0)910 {911 pVirtqBuf->u32Magic = ~VIRTQBUF_MAGIC;912 RTMemFree(pVirtqBuf);913 STAM_REL_COUNTER_INC(&pVirtio->StatDescChainsFreed);914 }915 return cRefs;916 }917 918 /** API Function: See header file */919 void virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio)920 {921 virtioKick(pVirtio->pDevInsR3, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig);922 }923 924 /** API Function: See header file */925 void virtioCoreVirtqEnableNotify(PVIRTIOCORE pVirtio, uint16_t uVirtq, bool fEnable)926 {927 928 Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues));929 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq];930 931 if (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK)932 {933 uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, pVirtq);934 935 if (fEnable)936 fFlags &= ~ VIRTQ_USED_F_NO_NOTIFY;937 else938 fFlags |= VIRTQ_USED_F_NO_NOTIFY;939 940 virtioWriteUsedRingFlags(pVirtio->pDevInsR3, pVirtio, pVirtq, fFlags);941 }942 }943 944 /** API function: See Header file */945 void virtioCoreResetAll(PVIRTIOCORE pVirtio)946 {947 LogFunc(("\n"));948 pVirtio->fDeviceStatus |= VIRTIO_STATUS_DEVICE_NEEDS_RESET;949 if (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK)950 {951 pVirtio->fGenUpdatePending = true;952 virtioKick(pVirtio->pDevInsR3, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig);953 }954 }955 956 /** API function: See Header file */957 int virtioCoreR3VirtqAvailBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq,958 PPVIRTQBUF ppVirtqBuf)959 {960 return virtioCoreR3VirtqAvailBufGet(pDevIns, pVirtio, uVirtq, ppVirtqBuf, false);961 }962 963 /** API function: See Header file */964 int virtioCoreR3VirtqAvailBufNext(PVIRTIOCORE pVirtio, uint16_t uVirtq)965 {966 Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues));967 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq];968 969 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtq->uEnable,970 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);971 972 if (IS_VIRTQ_EMPTY(pVirtio->pDevInsR3, pVirtio, pVirtq))973 return VERR_NOT_AVAILABLE;974 975 Log6Func(("%s avail shadow idx: %u\n", pVirtq->szName, pVirtq->uAvailIdxShadow));976 pVirtq->uAvailIdxShadow++;977 978 return VINF_SUCCESS;979 }980 981 860 /** API function: See Header file */ 982 861 int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq, … … 1027 906 cbRemain = cbTotal = RTSgBufCalcTotalLength(pSgVirtReturn); 1028 907 AssertMsgReturn(cbTarget >= cbRemain, ("No space to write data to phys memory"), VERR_BUFFER_OVERFLOW); 1029 virtioCoreGCPhysChainReset(pSgPhysReturn); /* Reset ptr because req data may have already been written */908 virtioCoreGCPhysChainReset(pSgPhysReturn); 1030 909 while (cbRemain) 1031 910 { … … 1064 943 } 1065 944 1066 /** API function: See Header file */1067 void virtioCoreR3VirqBufFill(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb)1068 {1069 uint8_t *pb = (uint8_t *)pv;1070 size_t cbLim = RT_MIN(pVirtqBuf->cbPhysReturn, cb);1071 while (cbLim)1072 {1073 size_t cbSeg = cbLim;1074 RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysReturn, &cbSeg);1075 PDMDevHlpPCIPhysWrite(pVirtio->pDevInsR3, GCPhys, pb, cbSeg);1076 pb += cbSeg;1077 cbLim -= cbSeg;1078 pVirtqBuf->cbPhysSend -= cbSeg;1079 }1080 LogFunc(("Added %d/%d bytes to %s buffer, head idx: %u (%d bytes remain)\n",1081 cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtq),1082 pVirtqBuf->uHeadIdx, pVirtqBuf->cbPhysReturn));1083 }1084 1085 1086 /** API function: See Header file */1087 void virtioCoreR3VirtqBufDrain(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb)1088 {1089 uint8_t *pb = (uint8_t *)pv;1090 size_t cbLim = RT_MIN(pVirtqBuf->cbPhysSend, cb);1091 while (cbLim)1092 {1093 size_t cbSeg = cbLim;1094 RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysSend, &cbSeg);1095 PDMDevHlpPCIPhysRead(pVirtio->pDevInsR3, GCPhys, pb, cbSeg);1096 pb += cbSeg;1097 cbLim -= cbSeg;1098 pVirtqBuf->cbPhysSend -= cbSeg;1099 }1100 LogFunc(("Drained %d/%d bytes from %s buffer, head idx: %u (%d bytes left)\n",1101 cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtq),1102 pVirtqBuf->uHeadIdx, pVirtqBuf->cbPhysSend));1103 }1104 945 1105 946 #endif /* IN_RING3 */ … … 1255 1096 pVirtq->uAvailIdxShadow = 0; 1256 1097 pVirtq->uUsedIdxShadow = 0; 1257 pVirtq->uEnable = false;1258 pVirtq->uSize = VIRTQ_MAX_ENTRIES;1259 pVirtq->uNotifyOffset = uVirtq;1260 pVirtq->uMsix = uVirtq + 2;1261 pVirtq->fUsedRingEvent = false;1098 pVirtq->uEnable = false; 1099 pVirtq->uSize = VIRTQ_MAX_ENTRIES; 1100 pVirtq->uNotifyOffset = uVirtq; 1101 pVirtq->uMsix = uVirtq + 2; 1102 pVirtq->fUsedRingEvent = false; 1262 1103 1263 1104 if (!pVirtio->fMsiSupport) /* VirtIO 1.0, 4.1.4.3 and 4.1.5.1.2 */ … … 1527 1368 AssertReturn(cb == 1 || cb == 2 || cb == 4, VERR_INVALID_PARAMETER); 1528 1369 Assert(pVirtio == (PVIRTIOCORE)pvUser); RT_NOREF(pvUser); 1529 1530 1370 1531 1371 uint32_t uOffset; … … 1849 1689 break; 1850 1690 case kvirtIoVmStateChangedResume: 1851 virtioCoreNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, 0 /* uVirtq */); 1691 for (int uVirtq = 0; uVirtq < VIRTQ_MAX_COUNT; uVirtq++) 1692 { 1693 if (pVirtio->aVirtqueues[uVirtq].uEnable) 1694 virtioCoreNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, uVirtq); 1695 } 1852 1696 break; 1853 1697 default: … … 1874 1718 } 1875 1719 1876 /** 1877 * Setup PCI device controller and Virtio state 1878 * 1879 * This should be called from PDMDEVREGR3::pfnConstruct. 1880 * 1881 * @param pDevIns The device instance. 1882 * @param pVirtio Pointer to the shared virtio state. This 1883 * must be the first member in the shared 1884 * device instance data! 1885 * @param pVirtioCC Pointer to the ring-3 virtio state. This 1886 * must be the first member in the ring-3 1887 * device instance data! 1888 * @param pPciParams Values to populate industry standard PCI Configuration Space data structure 1889 * @param pcszInstance Device instance name (format-specifier) 1890 * @param fDevSpecificFeatures VirtIO device-specific features offered by 1891 * client 1892 * @param cbDevSpecificCfg Size of virtio_pci_device_cap device-specific struct 1893 * @param pvDevSpecificCfg Address of client's dev-specific 1894 * configuration struct. 1895 */ 1720 /** API Function: See header file */ 1896 1721 int virtioCoreR3Init(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, PVIRTIOPCIPARAMS pPciParams, 1897 1722 const char *pcszInstance, uint64_t fDevSpecificFeatures, void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg) -
trunk/src/VBox/Devices/VirtIO/VirtioCore.h
r85194 r85291 402 402 403 403 /** 404 * Setup PCI device controller and Virtio state 405 * 406 * This should be called from PDMDEVREGR3::pfnConstruct. 407 * 408 * @param pDevIns The device instance. 409 * @param pVirtio Pointer to the shared virtio state. This 410 * must be the first member in the shared 411 * device instance data! 412 * @param pVirtioCC Pointer to the ring-3 virtio state. This 413 * must be the first member in the ring-3 414 * device instance data! 415 * @param pPciParams Values to populate industry standard PCI Configuration Space data structure 416 * @param pcszInstance Device instance name (format-specifier) 417 * @param fDevSpecificFeatures VirtIO device-specific features offered by 418 * client 419 * @param cbDevSpecificCfg Size of virtio_pci_device_cap device-specific struct 420 * @param pvDevSpecificCfg Address of client's dev-specific 421 * configuration struct. 422 */ 423 int virtioCoreR3Init(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, 424 PVIRTIOPCIPARAMS pPciParams, const char *pcszInstance, 425 uint64_t fDevSpecificFeatures, void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg); 426 427 /** 404 428 * Initiate orderly reset procedure. This is an exposed API for clients that might need it. 405 429 * Invoked by client to reset the device and driver (see VirtIO 1.0 section 2.1.1/2.1.2) … … 621 645 int virtioCoreR3VirtqAvailBufNext(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr); 622 646 647 648 DECLINLINE(void) virtioCoreGCPhysChainInit(PVIRTIOSGBUF pGcSgBuf, PVIRTIOSGSEG paSegs, size_t cSegs) 649 { 650 AssertPtr(pGcSgBuf); 651 Assert((cSegs > 0 && VALID_PTR(paSegs)) || (!cSegs && !paSegs)); 652 Assert(cSegs < (~(unsigned)0 >> 1)); 653 654 pGcSgBuf->paSegs = paSegs; 655 pGcSgBuf->cSegs = (unsigned)cSegs; 656 pGcSgBuf->idxSeg = 0; 657 if (cSegs && paSegs) 658 { 659 pGcSgBuf->GCPhysCur = paSegs[0].GCPhys; 660 pGcSgBuf->cbSegLeft = paSegs[0].cbSeg; 661 } 662 else 663 { 664 pGcSgBuf->GCPhysCur = 0; 665 pGcSgBuf->cbSegLeft = 0; 666 } 667 } 668 669 DECLINLINE(RTGCPHYS) virtioCoreGCPhysChainGet(PVIRTIOSGBUF pGcSgBuf, size_t *pcbData) 670 { 671 size_t cbData; 672 RTGCPHYS pGcBuf; 673 674 /* Check that the S/G buffer has memory left. */ 675 if (RT_LIKELY(pGcSgBuf->idxSeg < pGcSgBuf->cSegs && pGcSgBuf->cbSegLeft)) 676 { /* likely */ } 677 else 678 { 679 *pcbData = 0; 680 return 0; 681 } 682 683 AssertMsg( pGcSgBuf->cbSegLeft <= 128 * _1M 684 && (RTGCPHYS)pGcSgBuf->GCPhysCur >= (RTGCPHYS)pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys 685 && (RTGCPHYS)pGcSgBuf->GCPhysCur + pGcSgBuf->cbSegLeft <= 686 (RTGCPHYS)pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys + pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg, 687 ("pGcSgBuf->idxSeg=%d pGcSgBuf->cSegs=%d pGcSgBuf->GCPhysCur=%p pGcSgBuf->cbSegLeft=%zd " 688 "pGcSgBuf->paSegs[%d].GCPhys=%p pGcSgBuf->paSegs[%d].cbSeg=%zd\n", 689 pGcSgBuf->idxSeg, pGcSgBuf->cSegs, pGcSgBuf->GCPhysCur, pGcSgBuf->cbSegLeft, 690 pGcSgBuf->idxSeg, pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys, pGcSgBuf->idxSeg, 691 pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg)); 692 693 cbData = RT_MIN(*pcbData, pGcSgBuf->cbSegLeft); 694 pGcBuf = pGcSgBuf->GCPhysCur; 695 pGcSgBuf->cbSegLeft -= cbData; 696 if (!pGcSgBuf->cbSegLeft) 697 { 698 pGcSgBuf->idxSeg++; 699 700 if (pGcSgBuf->idxSeg < pGcSgBuf->cSegs) 701 { 702 pGcSgBuf->GCPhysCur = pGcSgBuf->paSegs[pGcSgBuf->idxSeg].GCPhys; 703 pGcSgBuf->cbSegLeft = pGcSgBuf->paSegs[pGcSgBuf->idxSeg].cbSeg; 704 } 705 *pcbData = cbData; 706 } 707 else 708 pGcSgBuf->GCPhysCur = pGcSgBuf->GCPhysCur + cbData; 709 710 return pGcBuf; 711 } 712 713 DECLINLINE(void) virtioCoreGCPhysChainReset(PVIRTIOSGBUF pGcSgBuf) 714 { 715 AssertPtrReturnVoid(pGcSgBuf); 716 717 pGcSgBuf->idxSeg = 0; 718 if (pGcSgBuf->cSegs) 719 { 720 pGcSgBuf->GCPhysCur = pGcSgBuf->paSegs[0].GCPhys; 721 pGcSgBuf->cbSegLeft = pGcSgBuf->paSegs[0].cbSeg; 722 } 723 else 724 { 725 pGcSgBuf->GCPhysCur = 0; 726 pGcSgBuf->cbSegLeft = 0; 727 } 728 } 729 730 DECLINLINE(RTGCPHYS) virtioCoreGCPhysChainAdvance(PVIRTIOSGBUF pGcSgBuf, size_t cbAdvance) 731 { 732 AssertReturn(pGcSgBuf, 0); 733 734 size_t cbLeft = cbAdvance; 735 while (cbLeft) 736 { 737 size_t cbThisAdvance = cbLeft; 738 virtioCoreGCPhysChainGet(pGcSgBuf, &cbThisAdvance); 739 if (!cbThisAdvance) 740 break; 741 742 cbLeft -= cbThisAdvance; 743 } 744 return cbAdvance - cbLeft; 745 } 746 747 DECLINLINE(RTGCPHYS) virtioCoreGCPhysChainGetNextSeg(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg) 748 { 749 AssertReturn(pGcSgBuf, 0); 750 AssertPtrReturn(pcbSeg, 0); 751 752 if (!*pcbSeg) 753 *pcbSeg = pGcSgBuf->cbSegLeft; 754 755 return virtioCoreGCPhysChainGet(pGcSgBuf, pcbSeg); 756 } 757 758 DECLINLINE(size_t) virtioCoreGCPhysChainCalcBufSize(PVIRTIOSGBUF pGcSgBuf) 759 { 760 size_t cb = 0; 761 unsigned i = pGcSgBuf->cSegs; 762 while (i-- > 0) 763 cb += pGcSgBuf->paSegs[i].cbSeg; 764 return cb; 765 } 766 767 #define VIRTQNAME(a_pVirtio, a_uVirtq) ((a_pVirtio)->aVirtqueues[(a_uVirtq)].szName) 768 623 769 /** 624 770 * Add some bytes to a virtq (s/g) buffer, converting them from virtual memory to GCPhys … … 632 778 * @param cb number of bytes to add to the s/g buffer. 633 779 */ 634 void virtioCoreR3VirqBufFill(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb); 780 DECLINLINE(void) virtioCoreR3VirqBufFill(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb) 781 { 782 uint8_t *pb = (uint8_t *)pv; 783 size_t cbLim = RT_MIN(pVirtqBuf->cbPhysReturn, cb); 784 while (cbLim) 785 { 786 size_t cbSeg = cbLim; 787 RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysReturn, &cbSeg); 788 PDMDevHlpPCIPhysWrite(pVirtio->pDevInsR3, GCPhys, pb, cbSeg); 789 pb += cbSeg; 790 cbLim -= cbSeg; 791 pVirtqBuf->cbPhysSend -= cbSeg; 792 } 793 LogFunc(("Added %d/%d bytes to %s buffer, head idx: %u (%d bytes remain)\n", 794 cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtq), 795 pVirtqBuf->uHeadIdx, pVirtqBuf->cbPhysReturn)); 796 } 635 797 636 798 /** … … 645 807 * @param cb number of bytes to Drain from buffer 646 808 */ 647 void virtioCoreR3VirtqBufDrain(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb); 809 DECLINLINE(void) virtioCoreR3VirtqBufDrain(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb) 810 { 811 uint8_t *pb = (uint8_t *)pv; 812 size_t cbLim = RT_MIN(pVirtqBuf->cbPhysSend, cb); 813 while (cbLim) 814 { 815 size_t cbSeg = cbLim; 816 RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysSend, &cbSeg); 817 PDMDevHlpPCIPhysRead(pVirtio->pDevInsR3, GCPhys, pb, cbSeg); 818 pb += cbSeg; 819 cbLim -= cbSeg; 820 pVirtqBuf->cbPhysSend -= cbSeg; 821 } 822 LogFunc(("Drained %d/%d bytes from %s buffer, head idx: %u (%d bytes left)\n", 823 cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtq), 824 pVirtqBuf->uHeadIdx, pVirtqBuf->cbPhysSend)); 825 } 826 827 #undef VIRTQNAME 648 828 649 829 /** … … 820 1000 void virtioCoreR3VmStateChanged(PVIRTIOCORE pVirtio, VIRTIOVMSTATECHANGED enmState); 821 1001 void virtioCoreR3Term(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC); 822 int virtioCoreR3Init(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, PVIRTIOPCIPARAMS pPciParams,823 const char *pcszInstance, uint64_t fDevSpecificFeatures, void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg);824 1002 int virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio); 825 1003 const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState);
Note:
See TracChangeset
for help on using the changeset viewer.