- Timestamp:
- Jun 12, 2020 8:00:27 PM (5 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 3 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Makefile.kmk
r84540 r84819 481 481 VBoxDD_SOURCES += \ 482 482 VirtIO/Virtio.cpp \ 483 VirtIO/Virtio _1_0.cpp \483 VirtIO/VirtioCore.cpp \ 484 484 Network/DevVirtioNet.cpp 485 485 endif … … 970 970 VBoxDDRC_SOURCES += \ 971 971 VirtIO/Virtio.cpp \ 972 VirtIO/Virtio _1_0.cpp \972 VirtIO/VirtioCore.cpp \ 973 973 Network/DevVirtioNet.cpp 974 974 endif … … 1169 1169 VBoxDDR0_SOURCES += \ 1170 1170 VirtIO/Virtio.cpp \ 1171 VirtIO/Virtio _1_0.cpp \1171 VirtIO/VirtioCore.cpp \ 1172 1172 Network/DevVirtioNet.cpp 1173 1173 endif -
trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp
r84806 r84819 55 55 # include <iprt/uuid.h> 56 56 #endif 57 #include "../VirtIO/Virtio _1_0.h"57 #include "../VirtIO/VirtioCore.h" 58 58 59 59 #include "VBoxDD.h" … … 67 67 #define VIRTIONET_PREALLOCATE_RX_SEG_COUNT 32 68 68 69 #define VIRTQNAME( idxVirtq) (pThis->aVirtqs[idxVirtq]->szName)70 #define CBVIRTQNAME( idxVirtq) RTStrNLen(VIRTQNAME(idxVirtq), sizeof(VIRTQNAME(idxVirtq)))69 #define VIRTQNAME(uVirtqNbr) (pThis->aVirtqs[uVirtqNbr]->szName) 70 #define CBVIRTQNAME(uVirtqNbr) RTStrNLen(VIRTQNAME(uVirtqNbr), sizeof(VIRTQNAME(uVirtqNbr))) 71 71 #define FEATURE_ENABLED(feature) RT_BOOL(pThis->fNegotiatedFeatures & VIRTIONET_F_##feature) 72 72 #define FEATURE_DISABLED(feature) (!FEATURE_ENABLED(feature)) 73 73 #define FEATURE_OFFERED(feature) VIRTIONET_HOST_FEATURES_OFFERED & VIRTIONET_F_##feature 74 74 75 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, idxVirtq) \76 (virtioCoreVirtqAvailCount(pDevIns, pVirtio, idxVirtq) == 0)75 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, uVirtqNbr) \ 76 (virtioCoreVirtqAvailCount(pDevIns, pVirtio, uVirtqNbr) == 0) 77 77 78 78 #define SET_LINK_UP(pState) \ … … 227 227 }; 228 228 #pragma pack() 229 typedef virtio_net_pkt_hdr VIRTIONET _PKT_HDR_T, *PVIRTIONET_PKT_HDR_T;230 AssertCompileSize(VIRTIONET _PKT_HDR_T, 12);229 typedef virtio_net_pkt_hdr VIRTIONETPKTHDR, *PVIRTIONETPKTHDR; 230 AssertCompileSize(VIRTIONETPKTHDR, 12); 231 231 232 232 /* Control virtq: Command entry (VirtIO 1.0, 5.1.6.5) */ … … 615 615 * @callback_method_impl{VIRTIOCORER0,pfnVirtqNotified} 616 616 */ 617 static DECLCALLBACK(void) virtioNetVirtqNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)617 static DECLCALLBACK(void) virtioNetVirtqNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 618 618 { 619 619 RT_NOREF(pVirtio); 620 620 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 621 621 622 PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[idxVirtq];622 PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[uVirtqNbr]; 623 623 PVIRTIONETWORKER pWorker = pVirtq->pWorker; 624 624 … … 627 627 #endif 628 628 629 if (IS_RX_VIRTQ( idxVirtq))630 { 631 uint16_t cBufsAvailable = virtioCoreVirtqAvailCount(pDevIns, pVirtio, idxVirtq);629 if (IS_RX_VIRTQ(uVirtqNbr)) 630 { 631 uint16_t cBufsAvailable = virtioCoreVirtqAvailCount(pDevIns, pVirtio, uVirtqNbr); 632 632 633 633 if (cBufsAvailable) … … 641 641 pThis->szInst, pVirtq->szName)); 642 642 } 643 else if (IS_TX_VIRTQ( idxVirtq) || IS_CTRL_VIRTQ(idxVirtq))643 else if (IS_TX_VIRTQ(uVirtqNbr) || IS_CTRL_VIRTQ(uVirtqNbr)) 644 644 { 645 645 /* Wake queue's worker thread up if sleeping (e.g. a Tx queue, or the control queue */ … … 663 663 } 664 664 else 665 LogRelFunc(("%s unrecognized queue %s (idx=%d) notified\n", pThis->szInst, pVirtq->szName, idxVirtq));665 LogRelFunc(("%s unrecognized queue %s (idx=%d) notified\n", pThis->szInst, pVirtq->szName, uVirtqNbr)); 666 666 } 667 667 … … 769 769 770 770 #ifdef LOG_ENABLED 771 void virtioNetDumpGcPhysRxBuf(PPDMDEVINS pDevIns, PVIRTIONET _PKT_HDR_TpRxPktHdr,771 void virtioNetDumpGcPhysRxBuf(PPDMDEVINS pDevIns, PVIRTIONETPKTHDR pRxPktHdr, 772 772 uint16_t cDescs, uint8_t *pvBuf, uint16_t cb, RTGCPHYS GCPhysRxBuf, uint8_t cbRxBuf) 773 773 { … … 789 789 pRxPktHdr->uChksumStart, pRxPktHdr->uChksumOffset, pRxPktHdr->uNumBuffers)); 790 790 791 virtioCoreHexDump((uint8_t *)pRxPktHdr, sizeof(VIRTIONET _PKT_HDR_T), 0, "Dump of virtual rPktHdr");791 virtioCoreHexDump((uint8_t *)pRxPktHdr, sizeof(VIRTIONETPKTHDR), 0, "Dump of virtual rPktHdr"); 792 792 } 793 793 virtioNetR3PacketDump(pThis, (const uint8_t *)pvBuf, cb, "<-- Incoming"); … … 841 841 pHlp->pfnPrintf(pHlp, "Virtq information:\n\n"); 842 842 843 for (int idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++)843 for (int uVirtqNbr = 0; uVirtqNbr < pThis->cVirtVirtqs; uVirtqNbr++) 844 844 { 845 PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[ idxVirtq];845 PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[uVirtqNbr]; 846 846 847 847 if (pVirtq->fHasWorker) … … 873 873 } 874 874 pHlp->pfnPrintf(pHlp, "\n"); 875 virtioCoreR3VirtqInfo(pDevIns, pHlp, pszArgs, idxVirtq);875 virtioCoreR3VirtqInfo(pDevIns, pHlp, pszArgs, uVirtqNbr); 876 876 pHlp->pfnPrintf(pHlp, " ---------------------------------------------------------------------\n"); 877 877 pHlp->pfnPrintf(pHlp, "\n"); … … 963 963 964 964 } 965 pHlp->pfnPrintf(pHlp, "\n"); 966 virtioCoreR3Info(pDevIns, pHlp, pszArgs); 965 /** @todo implement this 966 * pHlp->pfnPrintf(pHlp, "\n"); 967 * virtioCoreR3Info(pDevIns, pHlp, pszArgs); 968 */ 967 969 pHlp->pfnPrintf(pHlp, "\n"); 968 970 } … … 1139 1141 pHlp->pfnSSMGetU16( pSSM, &pThis->cWorkers); 1140 1142 1141 for (int idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++)1142 pHlp->pfnSSMGetBool(pSSM, &pThis->aVirtqs[ idxVirtq].fAttachedToVirtioCore);1143 for (int uVirtqNbr = 0; uVirtqNbr < pThis->cVirtVirtqs; uVirtqNbr++) 1144 pHlp->pfnSSMGetBool(pSSM, &pThis->aVirtqs[uVirtqNbr].fAttachedToVirtioCore); 1143 1145 1144 1146 int rc; … … 1228 1230 pHlp->pfnSSMPutU16( pSSM, pThis->cWorkers); 1229 1231 1230 for (int idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++)1231 pHlp->pfnSSMPutBool(pSSM, pThis->aVirtqs[ idxVirtq].fAttachedToVirtioCore);1232 for (int uVirtqNbr = 0; uVirtqNbr < pThis->cVirtVirtqs; uVirtqNbr++) 1233 pHlp->pfnSSMPutBool(pSSM, pThis->aVirtqs[uVirtqNbr].fAttachedToVirtioCore); 1232 1234 1233 1235 /* Save config area */ … … 1489 1491 rc = VINF_SUCCESS; 1490 1492 } 1491 virtioCoreVirtq NotifyEnable(&pThis->Virtio, pRxVirtq->idx, rc == VERR_INVALID_STATE /* fEnable */);1493 virtioCoreVirtqEnableNotify(&pThis->Virtio, pRxVirtq->idx, rc == VERR_INVALID_STATE /* fEnable */); 1492 1494 return rc; 1493 1495 } … … 1495 1497 static bool virtioNetR3RxBufsAvail(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETVIRTQ *pRxVirtq) 1496 1498 { 1497 for (int idxVirtqPair = 0; idxVirtqPair < pThis->cVirtqPairs; idxVirtqPair++)1498 { 1499 PVIRTIONETVIRTQ pThisRxVirtq = &pThis->aVirtqs[RXQIDX( idxVirtqPair)];1499 for (int uVirtqNbrPair = 0; uVirtqNbrPair < pThis->cVirtqPairs; uVirtqNbrPair++) 1500 { 1501 PVIRTIONETVIRTQ pThisRxVirtq = &pThis->aVirtqs[RXQIDX(uVirtqNbrPair)]; 1500 1502 if (RT_SUCCESS(virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pThisRxVirtq))) 1501 1503 { … … 1566 1568 * @param pCtx The context descriptor. 1567 1569 */ 1568 DECLINLINE(PPDMNETWORKGSO) virtioNetR3SetupGsoCtx(PPDMNETWORKGSO pGso, VIRTIONET _PKT_HDR_Tconst *pPktHdr)1570 DECLINLINE(PPDMNETWORKGSO) virtioNetR3SetupGsoCtx(PPDMNETWORKGSO pGso, VIRTIONETPKTHDR const *pPktHdr) 1569 1571 { 1570 1572 pGso->u8Type = PDMNETWORKGSOTYPE_INVALID; … … 1729 1731 1730 1732 static int virtioNetR3CopyRxPktToGuest(PPDMDEVINS pDevIns, PVIRTIONET pThis, const void *pvBuf, size_t cb, 1731 VIRTIONET _PKT_HDR_T*rxPktHdr, uint16_t cSegsAllocated,1733 VIRTIONETPKTHDR *rxPktHdr, uint16_t cSegsAllocated, 1732 1734 PRTSGBUF pVirtSegBufToGuest, PRTSGSEG paVirtSegsToGuest, 1733 1735 PVIRTIONETVIRTQ pRxVirtq) … … 1739 1741 for (cDescs = uOffset = 0; uOffset < cb; ) 1740 1742 { 1741 PVIRT IO_DESC_CHAIN_T pDescChain= NULL;1742 1743 int rc = virtioCoreR3Virtq Get(pDevIns, &pThis->Virtio, pRxVirtq->idx, &pDescChain, true);1743 PVIRTQBUF pVirtqBuf = NULL; 1744 1745 int rc = virtioCoreR3VirtqBufGet(pDevIns, &pThis->Virtio, pRxVirtq->idx, &pVirtqBuf, true); 1744 1746 AssertMsgReturn(rc == VINF_SUCCESS || rc == VERR_NOT_AVAILABLE, ("%Rrc\n", rc), rc); 1745 1747 1746 1748 /** @todo Find a better way to deal with this */ 1747 AssertMsgReturnStmt(rc == VINF_SUCCESS && p DescChain->cbPhysReturn,1749 AssertMsgReturnStmt(rc == VINF_SUCCESS && pVirtqBuf->cbPhysReturn, 1748 1750 ("Not enough Rx buffers in queue to accomodate ethernet packet\n"), 1749 virtioCoreR3 DescChainRelease(&pThis->Virtio, pDescChain),1751 virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf), 1750 1752 VERR_INTERNAL_ERROR); 1751 1753 … … 1754 1756 * virtio_net_header.num_buffers, to defer updating (in GCPhys). Re-visit if needed */ 1755 1757 1756 AssertMsgReturnStmt(p DescChain->pSgPhysReturn->paSegs[0].cbSeg >= sizeof(VIRTIONET_PKT_HDR_T),1758 AssertMsgReturnStmt(pVirtqBuf->pSgPhysReturn->paSegs[0].cbSeg >= sizeof(VIRTIONETPKTHDR), 1757 1759 ("Desc chain's first seg has insufficient space for pkt header!\n"), 1758 virtioCoreR3 DescChainRelease(&pThis->Virtio, pDescChain),1760 virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf), 1759 1761 VERR_INTERNAL_ERROR); 1760 1762 1761 size_t cbDescChainLeft = p DescChain->cbPhysReturn;1762 uint8_t cbHdr = sizeof(VIRTIONET _PKT_HDR_T);1763 size_t cbDescChainLeft = pVirtqBuf->cbPhysReturn; 1764 uint8_t cbHdr = sizeof(VIRTIONETPKTHDR); 1763 1765 1764 1766 /* Fill the Guest Rx buffer with data received from the interface */ … … 1776 1778 1777 1779 /* Calculate & cache addr of field to update after final value is known, in GCPhys mem */ 1778 GCPhysPktHdrNumBuffers = p DescChain->pSgPhysReturn->paSegs[0].GCPhys1779 + RT_UOFFSETOF(VIRTIONET _PKT_HDR_T, uNumBuffers);1780 GCPhysPktHdrNumBuffers = pVirtqBuf->pSgPhysReturn->paSegs[0].GCPhys 1781 + RT_UOFFSETOF(VIRTIONETPKTHDR, uNumBuffers); 1780 1782 fAddPktHdr = false; 1781 1783 cSegs++; … … 1787 1789 paVirtSegsToGuest = (PRTSGSEG)RTMemRealloc(paVirtSegsToGuest, sizeof(RTSGSEG) * cSegsAllocated); 1788 1790 if (!paVirtSegsToGuest) 1789 virtioCoreR3 DescChainRelease(&pThis->Virtio, pDescChain);1791 virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf); 1790 1792 AssertReturn(paVirtSegsToGuest, VERR_NO_MEMORY); 1791 1793 } … … 1802 1804 Log7Func(("Send Rx pkt to guest...\n")); 1803 1805 STAM_PROFILE_START(&pThis->StatReceiveStore, a); 1804 virtioCoreR3Virtq Put(pDevIns, &pThis->Virtio, pRxVirtq->idx,1805 pVirtSegBufToGuest, p DescChain, true /* fFence */);1806 virtioCoreR3VirtqBufPut(pDevIns, &pThis->Virtio, pRxVirtq->idx, 1807 pVirtSegBufToGuest, pVirtqBuf, true /* fFence */); 1806 1808 STAM_PROFILE_STOP(&pThis->StatReceiveStore, a); 1807 1809 … … 1810 1812 } 1811 1813 1812 virtioCoreR3 DescChainRelease(&pThis->Virtio, pDescChain);1814 virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf); 1813 1815 } 1814 1816 … … 1853 1855 1854 1856 LogFunc(("%s (%RTmac) pGso %s\n", pThis->szInst, pvBuf, pGso ? "present" : "not present")); 1855 VIRTIONET _PKT_HDR_TrxPktHdr = { 0 };1857 VIRTIONETPKTHDR rxPktHdr = { 0 }; 1856 1858 1857 1859 if (pGso) … … 1961 1963 selection algorithm feasible or even necessary to prevent starvation? */ 1962 1964 1963 for (int idxVirtqPair = 0; idxVirtqPair < pThis->cVirtqPairs; idxVirtqPair++)1964 { 1965 1966 PVIRTIONETVIRTQ pRxVirtq = &pThis->aVirtqs[RXQIDX( idxVirtqPair)];1965 for (int uVirtqNbrPair = 0; uVirtqNbrPair < pThis->cVirtqPairs; uVirtqNbrPair++) 1966 { 1967 1968 PVIRTIONETVIRTQ pRxVirtq = &pThis->aVirtqs[RXQIDX(uVirtqNbrPair)]; 1967 1969 if (RT_SUCCESS(!virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pRxVirtq))) 1968 1970 { … … 1998 2000 1999 2001 /* Read physical bytes from the out segment(s) of descriptor chain */ 2000 static void virtioNetR3PullChain(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRT IO_DESC_CHAIN_T pDescChain, void *pv, size_t cb)2002 static void virtioNetR3PullChain(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTQBUF pVirtqBuf, void *pv, size_t cb) 2001 2003 { 2002 2004 uint8_t *pb = (uint8_t *)pv; 2003 size_t cbLim = RT_MIN(p DescChain->cbPhysSend, cb);2005 size_t cbLim = RT_MIN(pVirtqBuf->cbPhysSend, cb); 2004 2006 while (cbLim) 2005 2007 { 2006 2008 size_t cbSeg = cbLim; 2007 RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(p DescChain->pSgPhysSend, &cbSeg);2009 RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pVirtqBuf->pSgPhysSend, &cbSeg); 2008 2010 PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pb, cbSeg); 2009 2011 pb += cbSeg; 2010 2012 cbLim -= cbSeg; 2011 p DescChain->cbPhysSend -= cbSeg;2013 pVirtqBuf->cbPhysSend -= cbSeg; 2012 2014 } 2013 2015 LogFunc(("%s Pulled %d/%d bytes from desc chain (%d bytes left)\n", 2014 pThis->szInst, cb - cbLim, cb, p DescChain->cbPhysSend));2016 pThis->szInst, cb - cbLim, cb, pVirtqBuf->cbPhysSend)); 2015 2017 RT_NOREF(pThis); 2016 2018 } 2017 2019 2018 2020 static uint8_t virtioNetR3CtrlRx(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 2019 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRT IO_DESC_CHAIN_T pDescChain)2021 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf) 2020 2022 { 2021 2023 … … 2044 2046 2045 2047 uint8_t fOn, fPromiscChanged = false; 2046 virtioNetR3PullChain(pDevIns, pThis, p DescChain, &fOn, (size_t)RT_MIN(pDescChain->cbPhysSend, sizeof(fOn)));2048 virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &fOn, (size_t)RT_MIN(pVirtqBuf->cbPhysSend, sizeof(fOn))); 2047 2049 2048 2050 switch(pCtrlPktHdr->uCmd) … … 2092 2094 2093 2095 static uint8_t virtioNetR3CtrlMac(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 2094 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRT IO_DESC_CHAIN_T pDescChain)2096 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf) 2095 2097 { 2096 2098 LogFunc(("%s Processing CTRL MAC command\n", pThis->szInst)); … … 2104 2106 AssertMsgReturn((v), ("DESC chain too small to process CTRL_MAC_TABLE_SET cmd\n"), VIRTIONET_ERROR) 2105 2107 2106 AssertMsgReturn(p DescChain->cbPhysSend >= sizeof(*pCtrlPktHdr),2108 AssertMsgReturn(pVirtqBuf->cbPhysSend >= sizeof(*pCtrlPktHdr), 2107 2109 ("insufficient descriptor space for ctrl pkt hdr"), 2108 2110 VIRTIONET_ERROR); 2109 2111 2110 size_t cbRemaining = p DescChain->cbPhysSend;2112 size_t cbRemaining = pVirtqBuf->cbPhysSend; 2111 2113 switch(pCtrlPktHdr->uCmd) 2112 2114 { … … 2115 2117 /* Set default Rx filter MAC */ 2116 2118 ASSERT_CTRL_ADDR_SET(cbRemaining >= sizeof(VIRTIONET_CTRL_MAC_TABLE_LEN)); 2117 virtioNetR3PullChain(pDevIns, pThis, p DescChain, &pThis->rxFilterMacDefault, sizeof(VIRTIONET_CTRL_MAC_TABLE_LEN));2119 virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &pThis->rxFilterMacDefault, sizeof(VIRTIONET_CTRL_MAC_TABLE_LEN)); 2118 2120 break; 2119 2121 } … … 2124 2126 /* Load unicast MAC filter table */ 2125 2127 ASSERT_CTRL_TABLE_SET(cbRemaining >= sizeof(cMacs)); 2126 virtioNetR3PullChain(pDevIns, pThis, p DescChain, &cMacs, sizeof(cMacs));2128 virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &cMacs, sizeof(cMacs)); 2127 2129 cbRemaining -= sizeof(cMacs); 2128 2130 Log7Func(("%s Guest provided %d unicast MAC Table entries\n", pThis->szInst, cMacs)); … … 2131 2133 uint32_t cbMacs = cMacs * sizeof(RTMAC); 2132 2134 ASSERT_CTRL_TABLE_SET(cbRemaining >= cbMacs); 2133 virtioNetR3PullChain(pDevIns, pThis, p DescChain, &pThis->aMacUnicastFilter, cbMacs);2135 virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &pThis->aMacUnicastFilter, cbMacs); 2134 2136 cbRemaining -= cbMacs; 2135 2137 } … … 2138 2140 /* Load multicast MAC filter table */ 2139 2141 ASSERT_CTRL_TABLE_SET(cbRemaining >= sizeof(cMacs)); 2140 virtioNetR3PullChain(pDevIns, pThis, p DescChain, &cMacs, sizeof(cMacs));2142 virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &cMacs, sizeof(cMacs)); 2141 2143 cbRemaining -= sizeof(cMacs); 2142 2144 Log10Func(("%s Guest provided %d multicast MAC Table entries\n", pThis->szInst, cMacs)); … … 2145 2147 uint32_t cbMacs = cMacs * sizeof(RTMAC); 2146 2148 ASSERT_CTRL_TABLE_SET(cbRemaining >= cbMacs); 2147 virtioNetR3PullChain(pDevIns, pThis, p DescChain, &pThis->aMacMulticastFilter, cbMacs);2149 virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &pThis->aMacMulticastFilter, cbMacs); 2148 2150 cbRemaining -= cbMacs; 2149 2151 } … … 2165 2167 2166 2168 static uint8_t virtioNetR3CtrlVlan(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 2167 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRT IO_DESC_CHAIN_T pDescChain)2169 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf) 2168 2170 { 2169 2171 LogFunc(("%s Processing CTRL VLAN command\n", pThis->szInst)); … … 2172 2174 2173 2175 uint16_t uVlanId; 2174 size_t cbRemaining = p DescChain->cbPhysSend - sizeof(*pCtrlPktHdr);2176 size_t cbRemaining = pVirtqBuf->cbPhysSend - sizeof(*pCtrlPktHdr); 2175 2177 AssertMsgReturn(cbRemaining > sizeof(uVlanId), 2176 2178 ("DESC chain too small for VIRTIO_NET_CTRL_VLAN cmd processing"), VIRTIONET_ERROR); 2177 virtioNetR3PullChain(pDevIns, pThis, p DescChain, &uVlanId, sizeof(uVlanId));2179 virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, &uVlanId, sizeof(uVlanId)); 2178 2180 AssertMsgReturn(uVlanId > VIRTIONET_MAX_VLAN_ID, 2179 2181 ("%s VLAN ID out of range (VLAN ID=%u)\n", pThis->szInst, uVlanId), VIRTIONET_ERROR); … … 2194 2196 2195 2197 static void virtioNetR3Ctrl(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 2196 PVIRT IO_DESC_CHAIN_T pDescChain)2198 PVIRTQBUF pVirtqBuf) 2197 2199 { 2198 2200 LogFunc(("%s Received CTRL packet from guest\n", pThis->szInst)); 2199 2201 2200 if (p DescChain->cbPhysSend < 2)2202 if (pVirtqBuf->cbPhysSend < 2) 2201 2203 { 2202 2204 LogFunc(("%s CTRL packet from guest driver incomplete. Skipping ctrl cmd\n", pThis->szInst)); 2203 2205 return; 2204 2206 } 2205 else if (p DescChain->cbPhysReturn < sizeof(VIRTIONET_CTRL_HDR_T_ACK))2207 else if (pVirtqBuf->cbPhysReturn < sizeof(VIRTIONET_CTRL_HDR_T_ACK)) 2206 2208 { 2207 2209 LogFunc(("%s Guest driver didn't allocate memory to receive ctrl pkt ACK. Skipping ctrl cmd\n", pThis->szInst)); … … 2216 2218 AssertPtrReturnVoid(pCtrlPktHdr); 2217 2219 2218 AssertMsgReturnVoid(p DescChain->cbPhysSend >= sizeof(VIRTIONET_CTRL_HDR_T),2220 AssertMsgReturnVoid(pVirtqBuf->cbPhysSend >= sizeof(VIRTIONET_CTRL_HDR_T), 2219 2221 ("DESC chain too small for CTRL pkt header")); 2220 2222 2221 virtioNetR3PullChain(pDevIns, pThis, p DescChain, pCtrlPktHdr,2222 RT_MIN(p DescChain->cbPhysSend, sizeof(VIRTIONET_CTRL_HDR_T)));2223 virtioNetR3PullChain(pDevIns, pThis, pVirtqBuf, pCtrlPktHdr, 2224 RT_MIN(pVirtqBuf->cbPhysSend, sizeof(VIRTIONET_CTRL_HDR_T))); 2223 2225 2224 2226 Log7Func(("%s CTRL COMMAND: class=%d command=%d\n", pThis->szInst, pCtrlPktHdr->uClass, pCtrlPktHdr->uCmd)); … … 2228 2230 { 2229 2231 case VIRTIONET_CTRL_RX: 2230 uAck = virtioNetR3CtrlRx(pDevIns, pThis, pThisCC, pCtrlPktHdr, p DescChain);2232 uAck = virtioNetR3CtrlRx(pDevIns, pThis, pThisCC, pCtrlPktHdr, pVirtqBuf); 2231 2233 break; 2232 2234 case VIRTIONET_CTRL_MAC: 2233 uAck = virtioNetR3CtrlMac(pDevIns, pThis, pThisCC, pCtrlPktHdr, p DescChain);2235 uAck = virtioNetR3CtrlMac(pDevIns, pThis, pThisCC, pCtrlPktHdr, pVirtqBuf); 2234 2236 break; 2235 2237 case VIRTIONET_CTRL_VLAN: 2236 uAck = virtioNetR3CtrlVlan(pDevIns, pThis, pThisCC, pCtrlPktHdr, p DescChain);2238 uAck = virtioNetR3CtrlVlan(pDevIns, pThis, pThisCC, pCtrlPktHdr, pVirtqBuf); 2237 2239 break; 2238 2240 case VIRTIONET_CTRL_ANNOUNCE: … … 2283 2285 RTSgBufInit(pReturnSegBuf, paReturnSegs, cSegs); 2284 2286 2285 virtioCoreR3Virtq Put(pDevIns, &pThis->Virtio, CTRLQIDX, pReturnSegBuf, pDescChain, true /* fFence */);2287 virtioCoreR3VirtqBufPut(pDevIns, &pThis->Virtio, CTRLQIDX, pReturnSegBuf, pVirtqBuf, true /* fFence */); 2286 2288 virtioCoreVirtqSync(pDevIns, &pThis->Virtio, CTRLQIDX); 2287 2289 … … 2296 2298 } 2297 2299 2298 static int virtioNetR3ReadHeader(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, PVIRTIONET _PKT_HDR_TpPktHdr, size_t cbFrame)2300 static int virtioNetR3ReadHeader(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, PVIRTIONETPKTHDR pPktHdr, size_t cbFrame) 2299 2301 { 2300 2302 int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pPktHdr, sizeof(*pPktHdr)); … … 2343 2345 2344 2346 static int virtioNetR3TransmitFrame(PVIRTIONET pThis, PVIRTIONETCC pThisCC, PPDMSCATTERGATHER pSgBuf, 2345 PPDMNETWORKGSO pGso, PVIRTIONET _PKT_HDR_TpPktHdr)2347 PPDMNETWORKGSO pGso, PVIRTIONETPKTHDR pPktHdr) 2346 2348 { 2347 2349 virtioNetR3PacketDump(pThis, (uint8_t *)pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, "--> Outgoing"); … … 2449 2451 2450 2452 int rc; 2451 PVIRT IO_DESC_CHAIN_T pDescChain= NULL;2452 while ((rc = virtioCoreR3Virtq Peek(pVirtio->pDevInsR3, pVirtio, pTxVirtq->idx, &pDescChain)) == VINF_SUCCESS)2453 PVIRTQBUF pVirtqBuf = NULL; 2454 while ((rc = virtioCoreR3VirtqBufPeek(pVirtio->pDevInsR3, pVirtio, pTxVirtq->idx, &pVirtqBuf)) == VINF_SUCCESS) 2453 2455 { 2454 2456 Log10Func(("%s fetched descriptor chain from %s\n", pThis->szInst, pTxVirtq->szName)); 2455 2457 2456 PVIRTIOSGBUF pSgPhysSend = p DescChain->pSgPhysSend;2458 PVIRTIOSGBUF pSgPhysSend = pVirtqBuf->pSgPhysSend; 2457 2459 PVIRTIOSGSEG paSegsFromGuest = pSgPhysSend->paSegs; 2458 2460 uint32_t cSegsFromGuest = pSgPhysSend->cSegs; 2459 2461 2460 VIRTIONET _PKT_HDR_TPktHdr;2462 VIRTIONETPKTHDR PktHdr; 2461 2463 size_t uSize = 0; 2462 2464 … … 2514 2516 2515 2517 LogFunc((".... Copied %lu bytes to %lu byte guest buffer, residual=%lu\n", 2516 cbTotal, p DescChain->cbPhysSend, pDescChain->cbPhysSend - cbTotal));2518 cbTotal, pVirtqBuf->cbPhysSend, pVirtqBuf->cbPhysSend - cbTotal)); 2517 2519 2518 2520 rc = virtioNetR3TransmitFrame(pThis, pThisCC, pSgBufToPdmLeafDevice, pGso, &PktHdr); … … 2531 2533 Log4Func(("Failed to allocate S/G buffer: size=%u rc=%Rrc\n", uSize, rc)); 2532 2534 /* Stop trying to fetch TX descriptors until we get more bandwidth. */ 2533 virtioCoreR3 DescChainRelease(pVirtio, pDescChain);2535 virtioCoreR3VirtqBufRelease(pVirtio, pVirtqBuf); 2534 2536 break; 2535 2537 } 2536 2538 2537 2539 /* Remove this descriptor chain from the available ring */ 2538 virtioCoreR3Virtq Skip(pVirtio, pTxVirtq->idx);2540 virtioCoreR3VirtqBufSkip(pVirtio, pTxVirtq->idx); 2539 2541 2540 2542 /* No data to return to guest, but call is needed put elem (e.g. desc chain) on used ring */ 2541 virtioCoreR3Virtq Put(pVirtio->pDevInsR3, pVirtio, pTxVirtq->idx, NULL, pDescChain, true /* fFence */);2543 virtioCoreR3VirtqBufPut(pVirtio->pDevInsR3, pVirtio, pTxVirtq->idx, NULL, pVirtqBuf, true /* fFence */); 2542 2544 2543 2545 /* Update used ring idx and notify guest that we've transmitted the data it sent */ … … 2545 2547 } 2546 2548 2547 virtioCoreR3 DescChainRelease(pVirtio, pDescChain);2548 p DescChain= NULL;2549 virtioCoreR3VirtqBufRelease(pVirtio, pVirtqBuf); 2550 pVirtqBuf = NULL; 2549 2551 } 2550 2552 virtioNetR3SetWriteLed(pThisCC, false); … … 2792 2794 2793 2795 uint16_t idxWorker = CTRLWIDX + 1; 2794 for (uint16_t idxVirtqPair = 0; idxVirtqPair < pThis->cVirtqPairs; idxVirtqPair++, idxWorker++)2795 { 2796 PVIRTIONETVIRTQ pTxVirtq = &pThis->aVirtqs[TXQIDX( idxVirtqPair)];2797 PVIRTIONETVIRTQ pRxVirtq = &pThis->aVirtqs[RXQIDX( idxVirtqPair)];2796 for (uint16_t uVirtqNbrPair = 0; uVirtqNbrPair < pThis->cVirtqPairs; uVirtqNbrPair++, idxWorker++) 2797 { 2798 PVIRTIONETVIRTQ pTxVirtq = &pThis->aVirtqs[TXQIDX(uVirtqNbrPair)]; 2799 PVIRTIONETVIRTQ pRxVirtq = &pThis->aVirtqs[RXQIDX(uVirtqNbrPair)]; 2798 2800 2799 2801 rc = virtioNetR3CreateOneWorkerThread(pDevIns, pThis, idxWorker, &pThis->aWorkers[idxWorker], … … 2825 2827 /** @todo Race w/guest enabling/disabling guest notifications cyclically. 2826 2828 See BugRef #8651, Comment #82 */ 2827 virtioCoreVirtq NotifyEnable(&pThis->Virtio, pVirtq->idx, true /* fEnable */);2829 virtioCoreVirtqEnableNotify(&pThis->Virtio, pVirtq->idx, true /* fEnable */); 2828 2830 2829 2831 while (pThread->enmState == PDMTHREADSTATE_RUNNING) … … 2857 2859 { 2858 2860 Log10Func(("%s %s worker woken. Fetching desc chain\n", pThis->szInst, pVirtq->szName)); 2859 PVIRT IO_DESC_CHAIN_T pDescChain= NULL;2860 int rc = virtioCoreR3Virtq Get(pDevIns, &pThis->Virtio, pVirtq->idx, &pDescChain, true);2861 PVIRTQBUF pVirtqBuf = NULL; 2862 int rc = virtioCoreR3VirtqBufGet(pDevIns, &pThis->Virtio, pVirtq->idx, &pVirtqBuf, true); 2861 2863 if (rc == VERR_NOT_AVAILABLE) 2862 2864 { … … 2864 2866 continue; 2865 2867 } 2866 virtioNetR3Ctrl(pDevIns, pThis, pThisCC, p DescChain);2867 virtioCoreR3 DescChainRelease(&pThis->Virtio, pDescChain);2868 virtioNetR3Ctrl(pDevIns, pThis, pThisCC, pVirtqBuf); 2869 virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf); 2868 2870 } 2869 2871 else /* Must be Tx queue */ … … 2911 2913 pThisCC->fQuiescing = false; 2912 2914 2913 for (unsigned idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++)2915 for (unsigned uVirtqNbr = 0; uVirtqNbr < pThis->cVirtVirtqs; uVirtqNbr++) 2914 2916 { 2915 PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[ idxVirtq];2916 pVirtq->idx = idxVirtq;2917 PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[uVirtqNbr]; 2918 pVirtq->idx = uVirtqNbr; 2917 2919 (void) virtioCoreR3VirtqAttach(&pThis->Virtio, pVirtq->idx, pVirtq->szName); 2918 2920 pVirtq->fAttachedToVirtioCore = true; 2919 2921 if (IS_VIRTQ_EMPTY(pThisCC->pDevIns, &pThis->Virtio, pVirtq->idx)) 2920 virtioCoreVirtq NotifyEnable(&pThis->Virtio, pVirtq->idx, true /* fEnable */);2922 virtioCoreVirtqEnableNotify(&pThis->Virtio, pVirtq->idx, true /* fEnable */); 2921 2923 } 2922 2924 } … … 2944 2946 pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, true); 2945 2947 2946 for (uint16_t idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++)2947 pThis->aVirtqs[ idxVirtq].fAttachedToVirtioCore = false;2948 for (uint16_t uVirtqNbr = 0; uVirtqNbr < pThis->cVirtVirtqs; uVirtqNbr++) 2949 pThis->aVirtqs[uVirtqNbr].fAttachedToVirtioCore = false; 2948 2950 } 2949 2951 } -
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r84803 r84819 51 51 # include <iprt/uuid.h> 52 52 #endif 53 #include "../VirtIO/Virtio _1_0.h"53 #include "../VirtIO/VirtioCore.h" 54 54 55 55 #include "VBoxSCSI.h" … … 112 112 #define VIRTQ_REQ_BASE 2 /**< Spec-defined base index of request queues */ 113 113 114 #define VIRTQNAME( idxVirtq) (pThis->aszVirtqNames[idxVirtq]) /**< Macro to get queue name from its index */115 #define CBVIRTQNAME( idxVirtq) RTStrNLen(VIRTQNAME(idxVirtq), sizeof(VIRTQNAME(idxVirtq)))116 117 #define IS_REQ_VIRTQ( idxVirtq) (idxVirtq >= VIRTQ_REQ_BASE && idxVirtq< VIRTIOSCSI_VIRTQ_CNT)114 #define VIRTQNAME(uVirtqNbr) (pThis->aszVirtqNames[uVirtqNbr]) /**< Macro to get queue name from its index */ 115 #define CBVIRTQNAME(uVirtqNbr) RTStrNLen(VIRTQNAME(uVirtqNbr), sizeof(VIRTQNAME(uVirtqNbr))) 116 117 #define IS_REQ_VIRTQ(uVirtqNbr) (uVirtqNbr >= VIRTQ_REQ_BASE && uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT) 118 118 119 119 #define VIRTIO_IS_IN_DIRECTION(pMediaExTxDirEnumValue) \ … … 123 123 ((pMediaExTxDirEnumValue) == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE) 124 124 125 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, idxVirtq) \126 (virtioCoreVirtqAvailCount(pDevIns, pVirtio, idxVirtq) == 0)125 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, uVirtqNbr) \ 126 (virtioCoreVirtqAvailCount(pDevIns, pVirtio, uVirtqNbr) == 0) 127 127 128 128 … … 557 557 PDMMEDIAEXIOREQ hIoReq; /**< Handle of I/O request */ 558 558 PVIRTIOSCSITARGET pTarget; /**< Target */ 559 uint16_t idxVirtq;/**< Index of queue this request arrived on */560 PVIRT IO_DESC_CHAIN_T pDescChain;/**< Prepared desc chain pulled from virtq avail ring */559 uint16_t uVirtqNbr; /**< Index of queue this request arrived on */ 560 PVIRTQBUF pVirtqBuf; /**< Prepared desc chain pulled from virtq avail ring */ 561 561 size_t cbDataIn; /**< size of dataout buffer */ 562 562 size_t cbDataOut; /**< size of dataout buffer */ … … 576 576 * @todo this causes burn if I prefix with at-sign. This callback is in VIRTIOCORER0 and VIRTIOCORER3 577 577 */ 578 static DECLCALLBACK(void) virtioScsiNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)578 static DECLCALLBACK(void) virtioScsiNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 579 579 { 580 580 … … 582 582 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 583 583 584 AssertReturnVoid( idxVirtq< VIRTIOSCSI_VIRTQ_CNT);585 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[ idxVirtq];584 AssertReturnVoid(uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT); 585 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[uVirtqNbr]; 586 586 587 587 #if defined (IN_RING3) && defined (LOG_ENABLED) … … 589 589 #endif 590 590 591 if ( idxVirtq == CONTROLQ_IDX || IS_REQ_VIRTQ(idxVirtq))592 { 593 Log6Func(("%s has available data\n", VIRTQNAME( idxVirtq)));591 if (uVirtqNbr == CONTROLQ_IDX || IS_REQ_VIRTQ(uVirtqNbr)) 592 { 593 Log6Func(("%s has available data\n", VIRTQNAME(uVirtqNbr))); 594 594 /* Wake queue's worker thread up if sleeping */ 595 595 if (!ASMAtomicXchgBool(&pWorker->fNotified, true)) … … 597 597 if (ASMAtomicReadBool(&pWorker->fSleeping)) 598 598 { 599 Log6Func(("waking %s worker.\n", VIRTQNAME( idxVirtq)));599 Log6Func(("waking %s worker.\n", VIRTQNAME(uVirtqNbr))); 600 600 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess); 601 601 AssertRC(rc); … … 603 603 } 604 604 } 605 else if ( idxVirtq== EVENTQ_IDX)606 { 607 Log3Func(("Driver queued buffer(s) to %s\n", VIRTQNAME( idxVirtq)));605 else if (uVirtqNbr == EVENTQ_IDX) 606 { 607 Log3Func(("Driver queued buffer(s) to %s\n", VIRTQNAME(uVirtqNbr))); 608 608 // if (ASMAtomicXchgBool(&pThis->fEventsMissed, false)) 609 609 // virtioScsiR3ReportEventsMissed(pDevIns, pThis, 0); 610 610 } 611 611 else 612 LogFunc(("Unexpected queue idx (ignoring): %d\n", idxVirtq));612 LogFunc(("Unexpected queue idx (ignoring): %d\n", uVirtqNbr)); 613 613 } 614 614 … … 621 621 RTStrCopy(pThis->aszVirtqNames[CONTROLQ_IDX], VIRTIO_MAX_VIRTQ_NAME_SIZE, "controlq"); 622 622 RTStrCopy(pThis->aszVirtqNames[EVENTQ_IDX], VIRTIO_MAX_VIRTQ_NAME_SIZE, "eventq"); 623 for (uint16_t idxVirtq = VIRTQ_REQ_BASE; idxVirtq < VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_VIRTQ_CNT; idxVirtq++)624 RTStrPrintf(pThis->aszVirtqNames[ idxVirtq], VIRTIO_MAX_VIRTQ_NAME_SIZE,625 "requestq<%d>", idxVirtq- VIRTQ_REQ_BASE);623 for (uint16_t uVirtqNbr = VIRTQ_REQ_BASE; uVirtqNbr < VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_VIRTQ_CNT; uVirtqNbr++) 624 RTStrPrintf(pThis->aszVirtqNames[uVirtqNbr], VIRTIO_MAX_VIRTQ_NAME_SIZE, 625 "requestq<%d>", uVirtqNbr - VIRTQ_REQ_BASE); 626 626 } 627 627 … … 754 754 } 755 755 756 PVIRT IO_DESC_CHAIN_T pDescChain= NULL;757 int rc = virtioCoreR3Virtq Get(pDevIns, &pThis->Virtio, EVENTQ_IDX, &pDescChain, true);756 PVIRTQBUF pVirtqBuf = NULL; 757 int rc = virtioCoreR3VirtqBufGet(pDevIns, &pThis->Virtio, EVENTQ_IDX, &pVirtqBuf, true); 758 758 if (rc == VERR_NOT_AVAILABLE) 759 759 { … … 783 783 RTSgBufInit(&ReqSgBuf, aReqSegs, RT_ELEMENTS(aReqSegs)); 784 784 785 rc = virtioCoreR3Virtq Put(pDevIns, &pThis->Virtio, EVENTQ_IDX, &ReqSgBuf, pDescChain, true /*fFence*/);785 rc = virtioCoreR3VirtqBufPut(pDevIns, &pThis->Virtio, EVENTQ_IDX, &ReqSgBuf, pVirtqBuf, true /*fFence*/); 786 786 if (rc == VINF_SUCCESS) 787 787 virtioCoreVirtqSync(pDevIns, &pThis->Virtio, EVENTQ_IDX, false); 788 788 else 789 789 LogRel(("Error writing control message to guest\n")); 790 virtioCoreR3 DescChainRelease(&pThis->Virtio, pDescChain);790 virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf); 791 791 792 792 return rc; … … 800 800 RTMemFree(pReq->pbSense); 801 801 pReq->pbSense = NULL; 802 virtioCoreR3 DescChainRelease(&pThis->Virtio, pReq->pDescChain);803 pReq->p DescChain= NULL;802 virtioCoreR3VirtqBufRelease(&pThis->Virtio, pReq->pVirtqBuf); 803 pReq->pVirtqBuf = NULL; 804 804 pTarget->pDrvMediaEx->pfnIoReqFree(pTarget->pDrvMediaEx, pReq->hIoReq); 805 805 } … … 811 811 * @param pThis VirtIO SCSI shared instance data. 812 812 * @param pThisCC VirtIO SCSI ring-3 instance data. 813 * @param idxVirtqVirtq index814 * @param p DescChainPointer to pre-processed descriptor chain pulled from virtq813 * @param uVirtqNbr Virtq index 814 * @param pVirtqBuf Pointer to pre-processed descriptor chain pulled from virtq 815 815 * @param pRespHdr Response header 816 816 * @param pbSense Pointer to sense buffer or NULL if none. … … 819 819 * @returns VINF_SUCCESS 820 820 */ 821 static int virtioScsiR3ReqErr(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, uint16_t idxVirtq,822 PVIRT IO_DESC_CHAIN_T pDescChain, REQ_RESP_HDR_T *pRespHdr, uint8_t *pbSense,821 static int virtioScsiR3ReqErr(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, uint16_t uVirtqNbr, 822 PVIRTQBUF pVirtqBuf, REQ_RESP_HDR_T *pRespHdr, uint8_t *pbSense, 823 823 size_t cbSenseCfg) 824 824 { … … 853 853 pRespHdr->uResponse = VIRTIOSCSI_S_RESET; 854 854 855 virtioCoreR3Virtq Put(pDevIns, &pThis->Virtio, idxVirtq, &ReqSgBuf, pDescChain, true /* fFence */);856 virtioCoreVirtqSync(pDevIns, &pThis->Virtio, idxVirtq);855 virtioCoreR3VirtqBufPut(pDevIns, &pThis->Virtio, uVirtqNbr, &ReqSgBuf, pVirtqBuf, true /* fFence */); 856 virtioCoreVirtqSync(pDevIns, &pThis->Virtio, uVirtqNbr); 857 857 858 858 if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThisCC->fQuiescing) … … 872 872 * @param pThis VirtIO SCSI shared instance data. 873 873 * @param pThisCC VirtIO SCSI ring-3 instance data. 874 * @param idxVirtqVirtq index875 * @param p DescChainPointer to pre-processed descriptor chain pulled from virtq874 * @param uVirtqNbr Virtq index 875 * @param pVirtqBuf Pointer to pre-processed descriptor chain pulled from virtq 876 876 * @param cbResidual The number of residual bytes or something like that. 877 877 * @param bStatus The SCSI status code. … … 883 883 * @returns VINF_SUCCESS 884 884 */ 885 static int virtioScsiR3ReqErr4(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, uint16_t idxVirtq,886 PVIRT IO_DESC_CHAIN_T pDescChain, size_t cbResidual, uint8_t bStatus, uint8_t bResponse,885 static int virtioScsiR3ReqErr4(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, uint16_t uVirtqNbr, 886 PVIRTQBUF pVirtqBuf, size_t cbResidual, uint8_t bStatus, uint8_t bResponse, 887 887 uint8_t *pbSense, size_t cbSense, size_t cbSenseCfg) 888 888 { … … 894 894 RespHdr.uResponse = bResponse; 895 895 896 return virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, &RespHdr, pbSense, cbSenseCfg);896 return virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, &RespHdr, pbSense, cbSenseCfg); 897 897 } 898 898 … … 993 993 { 994 994 LogFunc(("cbDataIn = %u, cbDataOut = %u (cbIn = %u, cbOut = %u)\n", 995 pReq->cbDataIn, pReq->cbDataOut, pReq->p DescChain->cbPhysReturn, pReq->pDescChain->cbPhysSend));995 pReq->cbDataIn, pReq->cbDataOut, pReq->pVirtqBuf->cbPhysReturn, pReq->pVirtqBuf->cbPhysSend)); 996 996 LogFunc(("xfer = %lu, residual = %u\n", cbXfer, cbResidual)); 997 997 LogFunc(("xfer direction: %s, sense written = %d, sense size = %d\n", … … 1016 1016 respHdr.uResidual = pReq->cbDataIn & UINT32_MAX; 1017 1017 1018 virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, pReq-> idxVirtq, pReq->pDescChain, &respHdr, abSense,1018 virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, pReq->uVirtqNbr, pReq->pVirtqBuf, &respHdr, abSense, 1019 1019 RT_MIN(pThis->virtioScsiConfig.uSenseSize, VIRTIOSCSI_SENSE_SIZE_MAX)); 1020 1020 } … … 1037 1037 size_t cbReqSgBuf = RTSgBufCalcTotalLength(&ReqSgBuf); 1038 1038 /** @todo r=bird: Returning here looks a little bogus... */ 1039 AssertMsgReturn(cbReqSgBuf <= pReq->p DescChain->cbPhysReturn,1039 AssertMsgReturn(cbReqSgBuf <= pReq->pVirtqBuf->cbPhysReturn, 1040 1040 ("Guest expected less req data (space needed: %zu, avail: %u)\n", 1041 cbReqSgBuf, pReq->p DescChain->cbPhysReturn),1041 cbReqSgBuf, pReq->pVirtqBuf->cbPhysReturn), 1042 1042 VERR_BUFFER_OVERFLOW); 1043 1043 1044 virtioCoreR3Virtq Put(pDevIns, &pThis->Virtio, pReq->idxVirtq, &ReqSgBuf, pReq->pDescChain, true /* fFence TBD */);1045 virtioCoreVirtqSync(pDevIns, &pThis->Virtio, pReq-> idxVirtq);1044 virtioCoreR3VirtqBufPut(pDevIns, &pThis->Virtio, pReq->uVirtqNbr, &ReqSgBuf, pReq->pVirtqBuf, true /* fFence TBD */); 1045 virtioCoreVirtqSync(pDevIns, &pThis->Virtio, pReq->uVirtqNbr); 1046 1046 1047 1047 Log2(("-----------------------------------------------------------------------------------------\n")); … … 1072 1072 return VINF_SUCCESS; 1073 1073 1074 AssertReturn(pReq->p DescChain, VERR_INVALID_PARAMETER);1075 1076 PVIRTIOSGBUF pSgPhysReturn = pReq->p DescChain->pSgPhysReturn;1074 AssertReturn(pReq->pVirtqBuf, VERR_INVALID_PARAMETER); 1075 1076 PVIRTIOSGBUF pSgPhysReturn = pReq->pVirtqBuf->pSgPhysReturn; 1077 1077 virtioCoreSgBufAdvance(pSgPhysReturn, offDst); 1078 1078 … … 1096 1096 1097 1097 Log3Func((".... Copied %lu bytes from %lu byte guest buffer, residual=%lu\n", 1098 cbCopy, pReq->p DescChain->cbPhysReturn, pReq->pDescChain->cbPhysReturn - cbCopy));1098 cbCopy, pReq->pVirtqBuf->cbPhysReturn, pReq->pVirtqBuf->cbPhysReturn - cbCopy)); 1099 1099 1100 1100 return VINF_SUCCESS; … … 1117 1117 return VINF_SUCCESS; 1118 1118 1119 PVIRTIOSGBUF pSgPhysSend = pReq->p DescChain->pSgPhysSend;1119 PVIRTIOSGBUF pSgPhysSend = pReq->pVirtqBuf->pSgPhysSend; 1120 1120 virtioCoreSgBufAdvance(pSgPhysSend, offSrc); 1121 1121 … … 1133 1133 1134 1134 Log2Func((".... Copied %lu bytes to %lu byte guest buffer, residual=%lu\n", 1135 cbCopy, pReq->p DescChain->cbPhysReturn, pReq->pDescChain->cbPhysReturn - cbCopy));1135 cbCopy, pReq->pVirtqBuf->cbPhysReturn, pReq->pVirtqBuf->cbPhysReturn - cbCopy)); 1136 1136 1137 1137 return VINF_SUCCESS; … … 1144 1144 */ 1145 1145 static int virtioScsiR3ReqSubmit(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, 1146 uint16_t idxVirtq, PVIRTIO_DESC_CHAIN_T pDescChain)1146 uint16_t uVirtqNbr, PVIRTQBUF pVirtqBuf) 1147 1147 { 1148 1148 … … 1164 1164 */ 1165 1165 size_t const cbReqHdr = sizeof(REQ_CMD_HDR_T) + cbCdb; 1166 AssertReturn(p DescChain->cbPhysSend >= cbReqHdr, VERR_INVALID_PARAMETER);1166 AssertReturn(pVirtqBuf->cbPhysSend >= cbReqHdr, VERR_INVALID_PARAMETER); 1167 1167 1168 1168 AssertCompile(VIRTIOSCSI_CDB_SIZE_MAX < 4096); … … 1182 1182 { 1183 1183 size_t cbSeg = cbReqHdr - offReq; 1184 RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(p DescChain->pSgPhysSend, &cbSeg);1184 RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pVirtqBuf->pSgPhysSend, &cbSeg); 1185 1185 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhys, &VirtqReq.ab[offReq], cbSeg); 1186 1186 offReq += cbSeg; … … 1218 1218 uint32_t const offDataOut = sizeof(REQ_CMD_HDR_T) + cbCdb; 1219 1219 uint32_t const offDataIn = sizeof(REQ_RESP_HDR_T) + cbSenseCfg; 1220 size_t const cbDataOut = p DescChain->cbPhysSend - offDataOut;1220 size_t const cbDataOut = pVirtqBuf->cbPhysSend - offDataOut; 1221 1221 /** @todo r=bird: Validate cbPhysReturn properly? I've just RT_MAX'ed it for now. */ 1222 size_t const cbDataIn = RT_MAX(p DescChain->cbPhysReturn, offDataIn) - offDataIn;1222 size_t const cbDataIn = RT_MAX(pVirtqBuf->cbPhysReturn, offDataIn) - offDataIn; 1223 1223 Assert(offDataOut <= UINT16_MAX); 1224 1224 Assert(offDataIn <= UINT16_MAX); … … 1232 1232 { 1233 1233 Log2Func(("Error submitting request, bad LUN format\n")); 1234 return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, cbDataIn + cbDataOut, 0 /*bStatus*/,1234 return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, cbDataIn + cbDataOut, 0 /*bStatus*/, 1235 1235 VIRTIOSCSI_S_FAILURE, NULL /*pbSense*/, 0 /*cbSense*/, cbSenseCfg); 1236 1236 } … … 1247 1247 0, SCSI_SENSE_ILLEGAL_REQUEST, 1248 1248 0, 0, 0, 0, 10, SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 0, 0 }; 1249 return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,1249 return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION, 1250 1250 VIRTIOSCSI_S_BAD_TARGET, abSense, sizeof(abSense), cbSenseCfg); 1251 1251 } … … 1258 1258 0, SCSI_SENSE_ILLEGAL_REQUEST, 1259 1259 0, 0, 0, 0, 10, SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 0, 0 }; 1260 return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,1260 return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION, 1261 1261 VIRTIOSCSI_S_OK, abSense, sizeof(abSense), cbSenseCfg); 1262 1262 } … … 1266 1266 { 1267 1267 Log2Func(("Aborting req submission because reset is in progress\n")); 1268 return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_OK,1268 return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, cbDataIn + cbDataOut, SCSI_STATUS_OK, 1269 1269 VIRTIOSCSI_S_RESET, NULL /*pbSense*/, 0 /*cbSense*/, cbSenseCfg); 1270 1270 } … … 1277 1277 uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED, 1278 1278 0, SCSI_SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 10, 0, 0, 0 }; 1279 return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION,1279 return virtioScsiR3ReqErr4(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, cbDataIn + cbDataOut, SCSI_STATUS_CHECK_CONDITION, 1280 1280 VIRTIOSCSI_S_FAILURE, abSense, sizeof(abSense), cbSenseCfg); 1281 1281 } … … 1295 1295 pReq->hIoReq = hIoReq; 1296 1296 pReq->pTarget = pTarget; 1297 pReq-> idxVirtq = idxVirtq;1297 pReq->uVirtqNbr = uVirtqNbr; 1298 1298 pReq->cbDataIn = cbDataIn; 1299 1299 pReq->cbDataOut = cbDataOut; 1300 pReq->p DescChain = pDescChain;1301 virtioCoreR3 DescChainRetain(pDescChain); /* (For pReq->pDescChain. Released by virtioScsiR3FreeReq.) */1300 pReq->pVirtqBuf = pVirtqBuf; 1301 virtioCoreR3VirtqBufRetain(pVirtqBuf); /* (For pReq->pVirtqBuf. Released by virtioScsiR3FreeReq.) */ 1302 1302 pReq->uDataInOff = offDataIn; 1303 1303 pReq->uDataOutOff = offDataOut; … … 1342 1342 respHdr.uResponse = VIRTIOSCSI_S_FAILURE; 1343 1343 respHdr.uResidual = (cbDataIn + cbDataOut) & UINT32_MAX; 1344 virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, idxVirtq, pDescChain, &respHdr, abSense, cbSenseCfg);1344 virtioScsiR3ReqErr(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf, &respHdr, abSense, cbSenseCfg); 1345 1345 virtioScsiR3FreeReq(pTarget, pReq); 1346 1346 } … … 1356 1356 * @param pThis VirtIO SCSI shared instance data. 1357 1357 * @param pThisCC VirtIO SCSI ring-3 instance data. 1358 * @param idxVirtqCONTROLQ_IDX1359 * @param p DescChainDescriptor chain to process.1358 * @param uVirtqNbr CONTROLQ_IDX 1359 * @param pVirtqBuf Descriptor chain to process. 1360 1360 */ 1361 1361 static int virtioScsiR3Ctrl(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, PVIRTIOSCSICC pThisCC, 1362 uint16_t idxVirtq, PVIRTIO_DESC_CHAIN_T pDescChain)1363 { 1364 AssertReturn(p DescChain->cbPhysSend >= RT_MIN(sizeof(VIRTIOSCSI_CTRL_AN_T),1362 uint16_t uVirtqNbr, PVIRTQBUF pVirtqBuf) 1363 { 1364 AssertReturn(pVirtqBuf->cbPhysSend >= RT_MIN(sizeof(VIRTIOSCSI_CTRL_AN_T), 1365 1365 sizeof(VIRTIOSCSI_CTRL_TMF_T)), 0); 1366 1366 … … 1371 1371 RT_ZERO(ScsiCtrlUnion); 1372 1372 1373 size_t const cbCtrl = RT_MIN(p DescChain->cbPhysSend, sizeof(VIRTIO_SCSI_CTRL_UNION_T));1373 size_t const cbCtrl = RT_MIN(pVirtqBuf->cbPhysSend, sizeof(VIRTIO_SCSI_CTRL_UNION_T)); 1374 1374 for (size_t offCtrl = 0; offCtrl < cbCtrl; ) 1375 1375 { 1376 1376 size_t cbSeg = cbCtrl - offCtrl; 1377 RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(p DescChain->pSgPhysSend, &cbSeg);1377 RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pVirtqBuf->pSgPhysSend, &cbSeg); 1378 1378 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhys, &ScsiCtrlUnion.ab[offCtrl], cbSeg); 1379 1379 offCtrl += cbSeg; … … 1381 1381 1382 1382 AssertReturn( (ScsiCtrlUnion.Type.uType == VIRTIOSCSI_T_TMF 1383 && p DescChain->cbPhysSend >= sizeof(VIRTIOSCSI_CTRL_TMF_T))1383 && pVirtqBuf->cbPhysSend >= sizeof(VIRTIOSCSI_CTRL_TMF_T)) 1384 1384 || ( ( ScsiCtrlUnion.Type.uType == VIRTIOSCSI_T_AN_QUERY 1385 1385 || ScsiCtrlUnion.Type.uType == VIRTIOSCSI_T_AN_SUBSCRIBE) 1386 && p DescChain->cbPhysSend >= sizeof(VIRTIOSCSI_CTRL_AN_T)),1386 && pVirtqBuf->cbPhysSend >= sizeof(VIRTIOSCSI_CTRL_AN_T)), 1387 1387 0 /** @todo r=bird: what kind of status is '0' here? */); 1388 1388 … … 1401 1401 uint32_t uScsiLun = RT_MAKE_U16(ScsiCtrlUnion.Tmf.abScsiLun[3], ScsiCtrlUnion.Tmf.abScsiLun[2]) & 0x3fff; 1402 1402 Log2Func(("[%s] (Target: %d LUN: %d) Task Mgt Function: %s\n", 1403 VIRTQNAME( idxVirtq), uTarget, uScsiLun, virtioGetTMFTypeText(ScsiCtrlUnion.Tmf.uSubtype)));1403 VIRTQNAME(uVirtqNbr), uTarget, uScsiLun, virtioGetTMFTypeText(ScsiCtrlUnion.Tmf.uSubtype))); 1404 1404 1405 1405 if (uTarget >= pThis->cTargets || !pThisCC->paTargetInstances[uTarget].fPresent) … … 1462 1462 virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), ScsiCtrlUnion.AsyncNotify.fEventsRequested); 1463 1463 Log2Func(("[%s] (Target: %d LUN: %d) Async. Notification Query: %s\n", 1464 VIRTQNAME( idxVirtq), uTarget, uScsiLun, szTypeText));1464 VIRTQNAME(uVirtqNbr), uTarget, uScsiLun, szTypeText)); 1465 1465 } 1466 1466 #endif … … 1487 1487 virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), ScsiCtrlUnion.AsyncNotify.fEventsRequested); 1488 1488 Log2Func(("[%s] (Target: %d LUN: %d) Async. Notification Subscribe: %s\n", 1489 VIRTQNAME( idxVirtq), uTarget, uScsiLun, szTypeText));1489 VIRTQNAME(uVirtqNbr), uTarget, uScsiLun, szTypeText)); 1490 1490 } 1491 1491 #endif … … 1508 1508 default: 1509 1509 { 1510 LogFunc(("Unknown control type extracted from %s: %u\n", VIRTQNAME( idxVirtq), ScsiCtrlUnion.Type.uType));1510 LogFunc(("Unknown control type extracted from %s: %u\n", VIRTQNAME(uVirtqNbr), ScsiCtrlUnion.Type.uType)); 1511 1511 1512 1512 bResponse = VIRTIOSCSI_S_FAILURE; … … 1527 1527 RTSgBufInit(&ReqSgBuf, aReqSegs, cSegs); 1528 1528 1529 virtioCoreR3Virtq Put(pDevIns, &pThis->Virtio, idxVirtq, &ReqSgBuf, pDescChain, true /*fFence*/);1530 virtioCoreVirtqSync(pDevIns, &pThis->Virtio, idxVirtq);1529 virtioCoreR3VirtqBufPut(pDevIns, &pThis->Virtio, uVirtqNbr, &ReqSgBuf, pVirtqBuf, true /*fFence*/); 1530 virtioCoreVirtqSync(pDevIns, &pThis->Virtio, uVirtqNbr); 1531 1531 1532 1532 return VINF_SUCCESS; … … 1547 1547 static DECLCALLBACK(int) virtioScsiR3WorkerThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 1548 1548 { 1549 uint16_t const idxVirtq= (uint16_t)(uintptr_t)pThread->pvUser;1549 uint16_t const uVirtqNbr = (uint16_t)(uintptr_t)pThread->pvUser; 1550 1550 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 1551 1551 PVIRTIOSCSICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC); 1552 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[ idxVirtq];1553 PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[ idxVirtq];1552 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[uVirtqNbr]; 1553 PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[uVirtqNbr]; 1554 1554 1555 1555 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) … … 1558 1558 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 1559 1559 { 1560 if (!pWorkerR3->cRedoDescs && IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, idxVirtq))1560 if (!pWorkerR3->cRedoDescs && IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, uVirtqNbr)) 1561 1561 { 1562 1562 /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */ … … 1565 1565 if (!fNotificationSent) 1566 1566 { 1567 Log6Func(("%s worker sleeping...\n", VIRTQNAME( idxVirtq)));1567 Log6Func(("%s worker sleeping...\n", VIRTQNAME(uVirtqNbr))); 1568 1568 Assert(ASMAtomicReadBool(&pWorker->fSleeping)); 1569 1569 int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pWorker->hEvtProcess, RT_INDEFINITE_WAIT); … … 1573 1573 if (rc == VERR_INTERRUPTED) 1574 1574 continue; 1575 Log6Func(("%s worker woken\n", VIRTQNAME( idxVirtq)));1575 Log6Func(("%s worker woken\n", VIRTQNAME(uVirtqNbr))); 1576 1576 ASMAtomicWriteBool(&pWorker->fNotified, false); 1577 1577 } … … 1579 1579 } 1580 1580 1581 if (!pThis->afVirtqAttached[ idxVirtq])1581 if (!pThis->afVirtqAttached[uVirtqNbr]) 1582 1582 { 1583 LogFunc(("%s queue not attached, worker aborting...\n", VIRTQNAME( idxVirtq)));1583 LogFunc(("%s queue not attached, worker aborting...\n", VIRTQNAME(uVirtqNbr))); 1584 1584 break; 1585 1585 } … … 1589 1589 for (int i = 0; i < pWorkerR3->cRedoDescs; i++) 1590 1590 { 1591 PVIRT IO_DESC_CHAIN_T pDescChain;1592 int rc = virtioCoreR3 DescChainGet(pDevIns, &pThis->Virtio, idxVirtq,1593 pWorkerR3->auRedoDescs[i], &p DescChain);1591 PVIRTQBUF pVirtqBuf; 1592 int rc = virtioCoreR3VirtqBufGet(pDevIns, &pThis->Virtio, uVirtqNbr, 1593 pWorkerR3->auRedoDescs[i], &pVirtqBuf); 1594 1594 if (RT_FAILURE(rc)) 1595 1595 LogRel(("Error fetching desc chain to redo, %Rrc", rc)); 1596 1596 1597 rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, idxVirtq, pDescChain);1597 rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf); 1598 1598 if (RT_FAILURE(rc)) 1599 1599 LogRel(("Error submitting req packet, resetting %Rrc", rc)); 1600 1600 1601 virtioCoreR3 DescChainRelease(&pThis->Virtio, pDescChain);1601 virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf); 1602 1602 } 1603 1603 pWorkerR3->cRedoDescs = 0; 1604 1604 1605 Log6Func(("fetching next descriptor chain from %s\n", VIRTQNAME( idxVirtq)));1606 PVIRT IO_DESC_CHAIN_T pDescChain= NULL;1607 int rc = virtioCoreR3Virtq Get(pDevIns, &pThis->Virtio, idxVirtq, &pDescChain, true);1605 Log6Func(("fetching next descriptor chain from %s\n", VIRTQNAME(uVirtqNbr))); 1606 PVIRTQBUF pVirtqBuf = NULL; 1607 int rc = virtioCoreR3VirtqBufGet(pDevIns, &pThis->Virtio, uVirtqNbr, &pVirtqBuf, true); 1608 1608 if (rc == VERR_NOT_AVAILABLE) 1609 1609 { 1610 Log6Func(("Nothing found in %s\n", VIRTQNAME( idxVirtq)));1610 Log6Func(("Nothing found in %s\n", VIRTQNAME(uVirtqNbr))); 1611 1611 continue; 1612 1612 } 1613 1613 1614 1614 AssertRC(rc); 1615 if ( idxVirtq== CONTROLQ_IDX)1616 virtioScsiR3Ctrl(pDevIns, pThis, pThisCC, idxVirtq, pDescChain);1615 if (uVirtqNbr == CONTROLQ_IDX) 1616 virtioScsiR3Ctrl(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf); 1617 1617 else /* request queue index */ 1618 1618 { 1619 rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, idxVirtq, pDescChain);1619 rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, uVirtqNbr, pVirtqBuf); 1620 1620 if (RT_FAILURE(rc)) 1621 1621 LogRel(("Error submitting req packet, resetting %Rrc", rc)); 1622 1622 } 1623 1623 1624 virtioCoreR3 DescChainRelease(&pThis->Virtio, pDescChain);1624 virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf); 1625 1625 } 1626 1626 } … … 1967 1967 1968 1968 virtioScsiSetVirtqNames(pThis); 1969 for (int idxVirtq = 0; idxVirtq < VIRTIOSCSI_VIRTQ_CNT; idxVirtq++)1970 pHlp->pfnSSMGetBool(pSSM, &pThis->afVirtqAttached[ idxVirtq]);1969 for (int uVirtqNbr = 0; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++) 1970 pHlp->pfnSSMGetBool(pSSM, &pThis->afVirtqAttached[uVirtqNbr]); 1971 1971 1972 1972 pHlp->pfnSSMGetU32(pSSM, &pThis->virtioScsiConfig.uNumVirtqs); … … 2007 2007 cReqsRedo, VIRTQ_MAX_ENTRIES)); 2008 2008 2009 for (uint16_t idxVirtq = VIRTQ_REQ_BASE; idxVirtq < VIRTIOSCSI_VIRTQ_CNT; idxVirtq++)2009 for (uint16_t uVirtqNbr = VIRTQ_REQ_BASE; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++) 2010 2010 { 2011 PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[ idxVirtq];2011 PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[uVirtqNbr]; 2012 2012 pWorkerR3->cRedoDescs = 0; 2013 2013 } … … 2015 2015 for (int i = 0; i < cReqsRedo; i++) 2016 2016 { 2017 uint16_t idxVirtq;2018 rc = pHlp->pfnSSMGetU16(pSSM, & idxVirtq);2017 uint16_t uVirtqNbr; 2018 rc = pHlp->pfnSSMGetU16(pSSM, &uVirtqNbr); 2019 2019 AssertRCReturn(rc, rc); 2020 AssertReturn( idxVirtq< VIRTIOSCSI_VIRTQ_CNT,2020 AssertReturn(uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT, 2021 2021 pHlp->pfnSSMSetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, 2022 2022 N_("Bad queue index for re-do in saved state (%#x, max %#x)"), 2023 idxVirtq, VIRTIOSCSI_VIRTQ_CNT - 1));2023 uVirtqNbr, VIRTIOSCSI_VIRTQ_CNT - 1)); 2024 2024 2025 2025 uint16_t idxHead; … … 2031 2031 idxHead, VIRTQ_MAX_ENTRIES - 1)); 2032 2032 2033 PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[ idxVirtq];2033 PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[uVirtqNbr]; 2034 2034 pWorkerR3->auRedoDescs[pWorkerR3->cRedoDescs++] = idxHead; 2035 2035 pWorkerR3->cRedoDescs %= VIRTQ_MAX_ENTRIES; … … 2045 2045 * Nudge request queue workers 2046 2046 */ 2047 for (int idxVirtq = VIRTQ_REQ_BASE; idxVirtq < VIRTIOSCSI_VIRTQ_CNT; idxVirtq++)2048 { 2049 if (pThis->afVirtqAttached[ idxVirtq])2047 for (int uVirtqNbr = VIRTQ_REQ_BASE; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++) 2048 { 2049 if (pThis->afVirtqAttached[uVirtqNbr]) 2050 2050 { 2051 LogFunc(("Waking %s worker.\n", VIRTQNAME( idxVirtq)));2052 int rc2 = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[ idxVirtq].hEvtProcess);2051 LogFunc(("Waking %s worker.\n", VIRTQNAME(uVirtqNbr))); 2052 int rc2 = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[uVirtqNbr].hEvtProcess); 2053 2053 AssertRCReturn(rc, rc2); 2054 2054 } … … 2069 2069 LogFunc(("SAVE EXEC!!\n")); 2070 2070 2071 for (int idxVirtq = 0; idxVirtq < VIRTIOSCSI_VIRTQ_CNT; idxVirtq++)2072 pHlp->pfnSSMPutBool(pSSM, pThis->afVirtqAttached[ idxVirtq]);2071 for (int uVirtqNbr = 0; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++) 2072 pHlp->pfnSSMPutBool(pSSM, pThis->afVirtqAttached[uVirtqNbr]); 2073 2073 2074 2074 pHlp->pfnSSMPutU32(pSSM, pThis->virtioScsiConfig.uNumVirtqs); … … 2117 2117 while(--cReqsRedo) 2118 2118 { 2119 pHlp->pfnSSMPutU16(pSSM, pReq-> idxVirtq);2120 pHlp->pfnSSMPutU16(pSSM, pReq->p DescChain->uHeadIdx);2119 pHlp->pfnSSMPutU16(pSSM, pReq->uVirtqNbr); 2120 pHlp->pfnSSMPutU16(pSSM, pReq->pVirtqBuf->uHeadIdx); 2121 2121 2122 2122 rc = pTarget->pDrvMediaEx->pfnIoReqQuerySuspendedNext(pTarget->pDrvMediaEx, hIoReq, … … 2335 2335 * be awake due to new reqs coming in. 2336 2336 */ 2337 for (uint16_t idxVirtq = 0; idxVirtq < VIRTIOSCSI_REQ_VIRTQ_CNT; idxVirtq++)2338 { 2339 if (ASMAtomicReadBool(&pThis->aWorkers[ idxVirtq].fSleeping))2337 for (uint16_t uVirtqNbr = 0; uVirtqNbr < VIRTIOSCSI_REQ_VIRTQ_CNT; uVirtqNbr++) 2338 { 2339 if (ASMAtomicReadBool(&pThis->aWorkers[uVirtqNbr].fSleeping)) 2340 2340 { 2341 Log6Func(("waking %s worker.\n", VIRTQNAME( idxVirtq)));2342 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[ idxVirtq].hEvtProcess);2341 Log6Func(("waking %s worker.\n", VIRTQNAME(uVirtqNbr))); 2342 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[uVirtqNbr].hEvtProcess); 2343 2343 AssertRC(rc); 2344 2344 } … … 2414 2414 pThisCC->pMediaNotify = NULL; 2415 2415 2416 for (unsigned idxVirtq = 0; idxVirtq < VIRTIOSCSI_VIRTQ_CNT; idxVirtq++)2417 { 2418 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[ idxVirtq];2416 for (unsigned uVirtqNbr = 0; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++) 2417 { 2418 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[uVirtqNbr]; 2419 2419 if (pWorker->hEvtProcess != NIL_SUPSEMEVENT) 2420 2420 { … … 2423 2423 } 2424 2424 2425 if (pThisCC->aWorkers[ idxVirtq].pThread)2425 if (pThisCC->aWorkers[uVirtqNbr].pThread) 2426 2426 { 2427 2427 /* Destroy the thread. */ 2428 2428 int rcThread; 2429 int rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->aWorkers[ idxVirtq].pThread, &rcThread);2429 int rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->aWorkers[uVirtqNbr].pThread, &rcThread); 2430 2430 if (RT_FAILURE(rc) || RT_FAILURE(rcThread)) 2431 2431 AssertMsgFailed(("%s Failed to destroythread rc=%Rrc rcThread=%Rrc\n", 2432 2432 __FUNCTION__, rc, rcThread)); 2433 pThisCC->aWorkers[ idxVirtq].pThread = NULL;2433 pThisCC->aWorkers[uVirtqNbr].pThread = NULL; 2434 2434 } 2435 2435 } … … 2526 2526 2527 2527 /* Attach the queues and create worker threads for them: */ 2528 for (uint16_t idxVirtq = 0; idxVirtq < VIRTIOSCSI_VIRTQ_CNT; idxVirtq++)2529 { 2530 rc = virtioCoreR3VirtqAttach(&pThis->Virtio, idxVirtq, VIRTQNAME(idxVirtq));2528 for (uint16_t uVirtqNbr = 0; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++) 2529 { 2530 rc = virtioCoreR3VirtqAttach(&pThis->Virtio, uVirtqNbr, VIRTQNAME(uVirtqNbr)); 2531 2531 if (RT_FAILURE(rc)) 2532 2532 continue; 2533 if ( idxVirtq == CONTROLQ_IDX || IS_REQ_VIRTQ(idxVirtq))2533 if (uVirtqNbr == CONTROLQ_IDX || IS_REQ_VIRTQ(uVirtqNbr)) 2534 2534 { 2535 rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->aWorkers[ idxVirtq].pThread,2536 (void *)(uintptr_t) idxVirtq, virtioScsiR3WorkerThread,2537 virtioScsiR3WorkerWakeUp, 0, RTTHREADTYPE_IO, VIRTQNAME( idxVirtq));2535 rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->aWorkers[uVirtqNbr].pThread, 2536 (void *)(uintptr_t)uVirtqNbr, virtioScsiR3WorkerThread, 2537 virtioScsiR3WorkerWakeUp, 0, RTTHREADTYPE_IO, VIRTQNAME(uVirtqNbr)); 2538 2538 if (rc != VINF_SUCCESS) 2539 2539 { 2540 LogRel(("Error creating thread for Virtual Virtq %s: %Rrc\n", VIRTQNAME( idxVirtq), rc));2540 LogRel(("Error creating thread for Virtual Virtq %s: %Rrc\n", VIRTQNAME(uVirtqNbr), rc)); 2541 2541 return rc; 2542 2542 } 2543 2543 2544 rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->aWorkers[ idxVirtq].hEvtProcess);2544 rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->aWorkers[uVirtqNbr].hEvtProcess); 2545 2545 if (RT_FAILURE(rc)) 2546 2546 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 2547 2547 N_("DevVirtioSCSI: Failed to create SUP event semaphore")); 2548 2548 } 2549 pThis->afVirtqAttached[ idxVirtq] = true;2549 pThis->afVirtqAttached[uVirtqNbr] = true; 2550 2550 } 2551 2551 -
trunk/src/VBox/Devices/VirtIO/VirtioCore.cpp
r84818 r84819 1 1 /* $Id$ */ 2 2 3 /** @file 3 * Virtio _1_0 - Virtio Common(PCI, feature & config mgt, queue mgt & proxy, notification mgt)4 * VirtioCore - Virtio Core (PCI, feature & config mgt, queue mgt & proxy, notification mgt) 4 5 */ 5 6 … … 35 36 #include <VBox/AssertGuest.h> 36 37 #include <VBox/vmm/pdmdev.h> 37 #include "Virtio _1_0.h"38 #include "VirtioCore.h" 38 39 39 40 … … 42 43 *********************************************************************************************************************************/ 43 44 #define INSTANCE(a_pVirtio) ((a_pVirtio)->szInstance) 44 #define VIRTQNAME(a_pVirtio, a_ idxVirtq) ((a_pVirtio)->aVirtqState[(a_idxVirtq)].szVirtqName)45 #define VIRTQNAME(a_pVirtio, a_uVirtqNbr) ((a_pVirtio)->aVirtqState[(a_uVirtqNbr)].szVirtqName) 45 46 #define IS_DRIVER_OK(a_pVirtio) ((a_pVirtio)->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK) 46 47 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtqState) \ … … 135 136 /* Internal Functions */ 136 137 137 static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq);138 static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr); 138 139 static int virtioKick(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint8_t uCause, uint16_t uVec); 139 140 … … 145 146 */ 146 147 #ifdef IN_RING3 147 DECLINLINE(void) virtioReadDesc(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq,148 DECLINLINE(void) virtioReadDesc(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, 148 149 uint32_t idxDesc, PVIRTQ_DESC_T pDesc) 149 150 { 150 151 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 151 uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[ idxVirtq], 1); /* Make sure to avoid div-by-zero. */152 uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */ 152 153 PDMDevHlpPCIPhysRead(pDevIns, 153 pVirtio->aGCPhysVirtqDesc[ idxVirtq] + sizeof(VIRTQ_DESC_T) * (idxDesc % cVirtqItems),154 pVirtio->aGCPhysVirtqDesc[uVirtqNbr] + sizeof(VIRTQ_DESC_T) * (idxDesc % cVirtqItems), 154 155 pDesc, sizeof(VIRTQ_DESC_T)); 155 156 } … … 160 161 */ 161 162 #ifdef IN_RING3 162 DECLINLINE(uint16_t) virtioReadAvailDescIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, uint32_t availIdx)163 DECLINLINE(uint16_t) virtioReadAvailDescIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint32_t availIdx) 163 164 { 164 165 uint16_t uDescIdx; 165 166 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 166 uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[ idxVirtq], 1); /* Make sure to avoid div-by-zero. */167 uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */ 167 168 PDMDevHlpPCIPhysRead(pDevIns, 168 pVirtio->aGCPhysVirtqAvail[ idxVirtq]169 pVirtio->aGCPhysVirtqAvail[uVirtqNbr] 169 170 + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[availIdx % cVirtqItems]), 170 171 &uDescIdx, sizeof(uDescIdx)); … … 172 173 } 173 174 174 DECLINLINE(uint16_t) virtioReadAvailUsedEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)175 DECLINLINE(uint16_t) virtioReadAvailUsedEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 175 176 { 176 177 uint16_t uUsedEventIdx; … … 178 179 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 179 180 PDMDevHlpPCIPhysRead(pDevIns, 180 pVirtio->aGCPhysVirtqAvail[ idxVirtq] + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[pVirtio->uVirtqSize[idxVirtq]]),181 pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[pVirtio->uVirtqSize[uVirtqNbr]]), 181 182 &uUsedEventIdx, sizeof(uUsedEventIdx)); 182 183 return uUsedEventIdx; … … 184 185 #endif 185 186 186 DECLINLINE(uint16_t) virtioReadAvailRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)187 DECLINLINE(uint16_t) virtioReadAvailRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 187 188 { 188 189 uint16_t uIdx = 0; 189 190 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 190 191 PDMDevHlpPCIPhysRead(pDevIns, 191 pVirtio->aGCPhysVirtqAvail[ idxVirtq] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx),192 pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx), 192 193 &uIdx, sizeof(uIdx)); 193 194 return uIdx; 194 195 } 195 196 196 DECLINLINE(uint16_t) virtioReadAvailRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)197 DECLINLINE(uint16_t) virtioReadAvailRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 197 198 { 198 199 uint16_t fFlags = 0; 199 200 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 200 201 PDMDevHlpPCIPhysRead(pDevIns, 201 pVirtio->aGCPhysVirtqAvail[ idxVirtq] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags),202 pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags), 202 203 &fFlags, sizeof(fFlags)); 203 204 return fFlags; … … 211 212 212 213 #ifdef IN_RING3 213 DECLINLINE(void) virtioWriteUsedElem(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq,214 DECLINLINE(void) virtioWriteUsedElem(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, 214 215 uint32_t usedIdx, uint32_t uDescIdx, uint32_t uLen) 215 216 { 216 217 VIRTQ_USED_ELEM_T elem = { uDescIdx, uLen }; 217 218 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 218 uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[ idxVirtq], 1); /* Make sure to avoid div-by-zero. */219 uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */ 219 220 PDMDevHlpPCIPhysWrite(pDevIns, 220 pVirtio->aGCPhysVirtqUsed[ idxVirtq] + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[usedIdx % cVirtqItems]),221 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[usedIdx % cVirtqItems]), 221 222 &elem, sizeof(elem)); 222 223 } 223 224 224 DECLINLINE(void) virtioWriteUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, uint16_t fFlags)225 DECLINLINE(void) virtioWriteUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint16_t fFlags) 225 226 { 226 227 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 227 228 RT_UNTRUSTED_VALIDATED_FENCE(); /* VirtIO 1.0, Section 3.2.1.4.1 */ 228 229 PDMDevHlpPCIPhysWrite(pDevIns, 229 pVirtio->aGCPhysVirtqUsed[ idxVirtq] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags),230 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags), 230 231 &fFlags, sizeof(fFlags)); 231 232 } 232 233 #endif 233 234 234 DECLINLINE(void) virtioWriteUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, uint16_t uIdx)235 DECLINLINE(void) virtioWriteUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint16_t uIdx) 235 236 { 236 237 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 237 238 PDMDevHlpPCIPhysWrite(pDevIns, 238 pVirtio->aGCPhysVirtqUsed[ idxVirtq] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx),239 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx), 239 240 &uIdx, sizeof(uIdx)); 240 241 } … … 243 244 #ifdef IN_RING3 244 245 245 DECLINLINE(uint16_t) virtioReadUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)246 DECLINLINE(uint16_t) virtioReadUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 246 247 { 247 248 uint16_t uIdx = 0; 248 249 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 249 250 PDMDevHlpPCIPhysRead(pDevIns, 250 pVirtio->aGCPhysVirtqUsed[ idxVirtq] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx),251 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx), 251 252 &uIdx, sizeof(uIdx)); 252 253 return uIdx; 253 254 } 254 255 255 DECLINLINE(uint16_t) virtioReadUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)256 DECLINLINE(uint16_t) virtioReadUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 256 257 { 257 258 uint16_t fFlags = 0; 258 259 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 259 260 PDMDevHlpPCIPhysRead(pDevIns, 260 pVirtio->aGCPhysVirtqUsed[ idxVirtq] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags),261 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags), 261 262 &fFlags, sizeof(fFlags)); 262 263 return fFlags; 263 264 } 264 265 265 DECLINLINE(void) virtioWriteUsedAvailEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, uint32_t uAvailEventIdx)266 DECLINLINE(void) virtioWriteUsedAvailEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint32_t uAvailEventIdx) 266 267 { 267 268 /** VirtIO 1.0 uAvailEventIdx (avail_event) immediately follows ring */ 268 269 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 269 270 PDMDevHlpPCIPhysWrite(pDevIns, 270 pVirtio->aGCPhysVirtqUsed[ idxVirtq] + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[pVirtio->uVirtqSize[idxVirtq]]),271 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[pVirtio->uVirtqSize[uVirtqNbr]]), 271 272 &uAvailEventIdx, sizeof(uAvailEventIdx)); 272 273 } … … 277 278 DECLINLINE(uint16_t) virtioCoreVirtqAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQSTATE pVirtqState) 278 279 { 279 uint16_t uIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, pVirtqState-> idxVirtq);280 uint16_t uIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, pVirtqState->uVirtqNbr); 280 281 uint16_t uShadow = pVirtqState->uAvailIdxShadow; 281 282 … … 287 288 288 289 LogFunc(("%s has %u %s (idx=%u shadow=%u)\n", 289 VIRTQNAME(pVirtio, pVirtqState-> idxVirtq), uDelta, uDelta == 1 ? "entry" : "entries",290 VIRTQNAME(pVirtio, pVirtqState->uVirtqNbr), uDelta, uDelta == 1 ? "entry" : "entries", 290 291 uIdx, uShadow)); 291 292 … … 297 298 * @param pDevIns The device instance. 298 299 * @param pVirtio Pointer to the shared virtio state. 299 * @param idxVirtqVirtq number300 * @param uVirtqNbr Virtq number 300 301 * 301 302 * @returns how many entries have been added to ring as a delta of the consumer's 302 303 * avail index and the queue's guest-side current avail index. 303 304 */ 304 uint16_t virtioCoreVirtqAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)305 { 306 if (!IS_DRIVER_OK(pVirtio) || !pVirtio->uVirtqEnable[ idxVirtq])305 uint16_t virtioCoreVirtqAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 306 { 307 if (!IS_DRIVER_OK(pVirtio) || !pVirtio->uVirtqEnable[uVirtqNbr]) 307 308 { 308 309 LogRelFunc(("Driver not ready or queue not enabled\n")); 309 310 return 0; 310 311 } 311 return virtioCoreVirtqAvailCount(pDevIns, pVirtio, &pVirtio->aVirtqState[ idxVirtq]);312 return virtioCoreVirtqAvailCount(pDevIns, pVirtio, &pVirtio->aVirtqState[uVirtqNbr]); 312 313 } 313 314 … … 435 436 436 437 #ifdef IN_RING3 438 439 /** API Function: See header file*/ 437 440 void virtioCorePrintFeatures(VIRTIOCORE *pVirtio, PCDBGFINFOHLP pHlp) 438 441 { … … 478 481 479 482 #ifdef LOG_ENABLED 480 /** 481 * Debug assist for consumer device code. 482 * Does a formatted hex dump using Log(()), recommend using VIRTIO_HEX_DUMP() macro to 483 * control enabling of logging efficiently. 484 * 485 * @param pv pointer to buffer to dump contents of 486 * @param cb count of characters to dump from buffer 487 * @param uBase base address of per-row address prefixing of hex output 488 * @param pszTitle Optional title. If present displays title that lists 489 * provided text with value of cb to indicate size next to it. 490 */ 483 484 /** API Function: See header file */ 491 485 void virtioCoreHexDump(uint8_t *pv, uint32_t cb, uint32_t uBase, const char *pszTitle) 492 486 { … … 527 521 } 528 522 529 /** 530 * Debug assist for consumer device code. 531 * Do a hex dump of memory in guest physical context 532 * 533 * @param GCPhys pointer to buffer to dump contents of 534 * @param cb count of characters to dump from buffer 535 * @param uBase base address of per-row address prefixing of hex output 536 * @param pszTitle Optional title. If present displays title that lists 537 * provided text with value of cb to indicate size next to it. 538 */ 523 /* API FUnction: See header file */ 539 524 void virtioCoreGCPhysHexDump(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint16_t cb, uint32_t uBase, const char *pszTitle) 540 525 { … … 579 564 #endif /* LOG_ENABLED */ 580 565 581 /** 582 * Log memory-mapped I/O input or output value. 583 * 584 * This is designed to be invoked by macros that can make contextual assumptions 585 * (e.g. implicitly derive MACRO parameters from the invoking function). It is exposed 586 * for the VirtIO client doing the device-specific implementation in order to log in a 587 * similar fashion accesses to the device-specific MMIO configuration structure. Macros 588 * that leverage this function are found in virtioCommonCfgAccessed() and can be 589 * used as an example of how to use this effectively for the device-specific 590 * code. 591 * 592 * @param pszFunc To avoid displaying this function's name via __FUNCTION__ or LogFunc() 593 * @param pszMember Name of struct member 594 * @param pv pointer to value 595 * @param cb size of value 596 * @param uOffset offset into member where value starts 597 * @param fWrite True if write I/O 598 * @param fHasIndex True if the member is indexed 599 * @param idx The index if fHasIndex 600 */ 566 /** API function: See header file */ 601 567 void virtioCoreLogMappedIoValue(const char *pszFunc, const char *pszMember, uint32_t uMemberSize, 602 568 const void *pv, uint32_t cb, uint32_t uOffset, int fWrite, … … 673 639 #ifdef IN_RING3 674 640 675 void virtioCoreR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) 676 { 677 RT_NOREF(pDevIns); 678 bool fNone = pszArgs && *pszArgs == '\0'; 679 bool fAll = pszArgs && (*pszArgs == 'a' || *pszArgs == 'A'); /* "all" */ 680 bool fBasic = pszArgs && (*pszArgs == 'b' || *pszArgs == 'B'); /* "basic" */ 681 bool fState = pszArgs && (*pszArgs == 's' || *pszArgs == 'S'); /* "state" */ 682 bool fPointers = pszArgs && (*pszArgs == 'p' || *pszArgs == 'P'); /* "pointers" */ 683 bool fVirtqs = pszArgs && (*pszArgs == 'q' || *pszArgs == 'Q'); /* "queues */ 684 RT_NOREF6(fNone, fAll, fBasic, fState, fPointers, fVirtqs); 685 pHlp->pfnPrintf(pHlp, ""); 686 687 } 688 689 void virtioCoreR3VirtqInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int idxVirtq) 641 /** API Fuunction: See header file */ 642 void virtioCoreR3VirtqInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int uVirtqNbr) 690 643 { 691 644 RT_NOREF(pszArgs); 692 645 PVIRTIOCORE pVirtio = PDMDEVINS_2_DATA(pDevIns, PVIRTIOCORE); 693 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq]; 694 695 // bool fDump = pszArgs && (*pszArgs == 'd' || *pszArgs == 'D'); /* "dump" (avail phys descriptor)" */ 696 697 uint16_t uAvailIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, idxVirtq); 646 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 647 648 /** @todo add ability to dump physical contents of any descriptor (using existing VirtIO core API function) */ 649 // bool fDump = pszArgs && (*pszArgs == 'd' || *pszArgs == 'D'); /* "dump" (avail phys descriptor)" 650 651 uint16_t uAvailIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, uVirtqNbr); 698 652 uint16_t uAvailIdxShadow = pVirtqState->uAvailIdxShadow; 699 653 700 uint16_t uUsedIdx = virtioReadUsedRingIdx(pDevIns, pVirtio, idxVirtq);654 uint16_t uUsedIdx = virtioReadUsedRingIdx(pDevIns, pVirtio, uVirtqNbr); 701 655 uint16_t uUsedIdxShadow = pVirtqState->uUsedIdxShadow; 702 656 703 PVIRT IO_DESC_CHAIN_T pDescChain= NULL;657 PVIRTQBUF pVirtqBuf = NULL; 704 658 705 659 bool fEmpty = IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtqState); 706 660 707 LogFunc(("%s, empty = %s\n", VIRTQNAME(pVirtio, idxVirtq), fEmpty ? "true" : "false"));661 LogFunc(("%s, empty = %s\n", VIRTQNAME(pVirtio, uVirtqNbr), fEmpty ? "true" : "false")); 708 662 709 663 int cSendSegs = 0, cReturnSegs = 0; 710 664 if (!fEmpty) 711 665 { 712 virtioCoreR3Virtq Peek(pDevIns, pVirtio, idxVirtq, &pDescChain);713 cSendSegs = p DescChain->pSgPhysSend ? pDescChain->pSgPhysSend->cSegs : 0;714 cReturnSegs = p DescChain->pSgPhysReturn ? pDescChain->pSgPhysReturn->cSegs : 0;715 } 716 717 bool fAvailNoInterrupt = virtioReadAvailRingFlags(pDevIns, pVirtio, idxVirtq) & VIRTQ_AVAIL_F_NO_INTERRUPT;718 bool fUsedNoNotify = virtioReadUsedRingFlags(pDevIns, pVirtio, idxVirtq) & VIRTQ_USED_F_NO_NOTIFY;719 720 721 pHlp->pfnPrintf(pHlp, " queue enabled: ........... %s\n", pVirtio->uVirtqEnable[ idxVirtq] ? "true" : "false");722 pHlp->pfnPrintf(pHlp, " size: .................... %d\n", pVirtio->uVirtqSize[ idxVirtq]);723 pHlp->pfnPrintf(pHlp, " notify offset: ........... %d\n", pVirtio->uVirtqNotifyOff[ idxVirtq]);666 virtioCoreR3VirtqBufPeek(pDevIns, pVirtio, uVirtqNbr, &pVirtqBuf); 667 cSendSegs = pVirtqBuf->pSgPhysSend ? pVirtqBuf->pSgPhysSend->cSegs : 0; 668 cReturnSegs = pVirtqBuf->pSgPhysReturn ? pVirtqBuf->pSgPhysReturn->cSegs : 0; 669 } 670 671 bool fAvailNoInterrupt = virtioReadAvailRingFlags(pDevIns, pVirtio, uVirtqNbr) & VIRTQ_AVAIL_F_NO_INTERRUPT; 672 bool fUsedNoNotify = virtioReadUsedRingFlags(pDevIns, pVirtio, uVirtqNbr) & VIRTQ_USED_F_NO_NOTIFY; 673 674 675 pHlp->pfnPrintf(pHlp, " queue enabled: ........... %s\n", pVirtio->uVirtqEnable[uVirtqNbr] ? "true" : "false"); 676 pHlp->pfnPrintf(pHlp, " size: .................... %d\n", pVirtio->uVirtqSize[uVirtqNbr]); 677 pHlp->pfnPrintf(pHlp, " notify offset: ........... %d\n", pVirtio->uVirtqNotifyOff[uVirtqNbr]); 724 678 if (pVirtio->fMsiSupport) 725 pHlp->pfnPrintf(pHlp, " MSIX vector: ....... %4.4x\n", pVirtio->uVirtqMsixVector[ idxVirtq]);679 pHlp->pfnPrintf(pHlp, " MSIX vector: ....... %4.4x\n", pVirtio->uVirtqMsixVector[uVirtqNbr]); 726 680 pHlp->pfnPrintf(pHlp, "\n"); 727 681 pHlp->pfnPrintf(pHlp, " avail ring (%d entries):\n", uAvailIdx - uAvailIdxShadow); … … 740 694 pHlp->pfnPrintf(pHlp, " head idx: ............. %d\n", uUsedIdx); 741 695 pHlp->pfnPrintf(pHlp, " segs: ................. %d\n", cSendSegs + cReturnSegs); 742 pHlp->pfnPrintf(pHlp, " refCnt ................ %d\n", p DescChain->cRefs);696 pHlp->pfnPrintf(pHlp, " refCnt ................ %d\n", pVirtqBuf->cRefs); 743 697 pHlp->pfnPrintf(pHlp, "\n"); 744 pHlp->pfnPrintf(pHlp, " host-to-guest (%d bytes):\n", p DescChain->cbPhysSend);698 pHlp->pfnPrintf(pHlp, " host-to-guest (%d bytes):\n", pVirtqBuf->cbPhysSend); 745 699 pHlp->pfnPrintf(pHlp, " segs: .............. %d\n", cSendSegs); 746 700 if (cSendSegs) 747 701 { 748 pHlp->pfnPrintf(pHlp, " index: ............. %d\n", p DescChain->pSgPhysSend->idxSeg);749 pHlp->pfnPrintf(pHlp, " unsent ............. %d\n", p DescChain->pSgPhysSend->cbSegLeft);702 pHlp->pfnPrintf(pHlp, " index: ............. %d\n", pVirtqBuf->pSgPhysSend->idxSeg); 703 pHlp->pfnPrintf(pHlp, " unsent ............. %d\n", pVirtqBuf->pSgPhysSend->cbSegLeft); 750 704 } 751 705 pHlp->pfnPrintf(pHlp, "\n"); 752 pHlp->pfnPrintf(pHlp, " guest-to-host (%d bytes)\n", p DescChain->cbPhysReturn);706 pHlp->pfnPrintf(pHlp, " guest-to-host (%d bytes)\n", pVirtqBuf->cbPhysReturn); 753 707 pHlp->pfnPrintf(pHlp, " segs: .............. %d\n", cReturnSegs); 754 708 if (cReturnSegs) 755 709 { 756 pHlp->pfnPrintf(pHlp, " index: ............. %d\n", p DescChain->pSgPhysReturn->idxSeg);757 pHlp->pfnPrintf(pHlp, " unsent ............. %d\n", p DescChain->pSgPhysReturn->cbSegLeft);710 pHlp->pfnPrintf(pHlp, " index: ............. %d\n", pVirtqBuf->pSgPhysReturn->idxSeg); 711 pHlp->pfnPrintf(pHlp, " unsent ............. %d\n", pVirtqBuf->pSgPhysReturn->cbSegLeft); 758 712 } 759 713 } else … … 763 717 } 764 718 765 /** 766 * Allocate client context for client to work with VirtIO-#provided with queue 767 * 768 * @param pVirtio Pointer to the shared virtio state. 769 * @param idxVirtq Virtq number 770 * @param pcszName Name to give queue 771 * 772 * @returns VBox status code. 773 */ 774 int virtioCoreR3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t idxVirtq, const char *pcszName) 719 int virtioCoreR3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, const char *pcszName) 775 720 { 776 721 LogFunc(("%s\n", pcszName)); 777 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[ idxVirtq];778 pVirtqState-> idxVirtq = idxVirtq;722 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 723 pVirtqState->uVirtqNbr = uVirtqNbr; 779 724 pVirtqState->uAvailIdxShadow = 0; 780 725 pVirtqState->uUsedIdxShadow = 0; … … 788 733 #ifdef IN_RING3 789 734 790 int virtioCoreR3DescChainGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, 791 uint16_t uHeadIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain) 792 { 793 AssertReturn(ppDescChain, VERR_INVALID_POINTER); 794 *ppDescChain = NULL; 795 796 Assert(idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState)); 797 798 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq]; 799 800 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[idxVirtq], 735 /** API Function: See header file */ 736 int virtioCoreR3VirtqBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, 737 uint16_t uHeadIdx, PPVIRTQBUF ppVirtqBuf) 738 { 739 AssertReturn(ppVirtqBuf, VERR_INVALID_POINTER); 740 *ppVirtqBuf = NULL; 741 742 Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 743 744 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 745 746 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[uVirtqNbr], 801 747 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 802 748 … … 809 755 * Allocate and initialize the descriptor chain structure. 810 756 */ 811 PVIRT IO_DESC_CHAIN_T pDescChain = (PVIRTIO_DESC_CHAIN_T)RTMemAllocZ(sizeof(VIRTIO_DESC_CHAIN_T));812 AssertReturn(p DescChain, VERR_NO_MEMORY);813 p DescChain->u32Magic = VIRTIO_DESC_CHAIN_MAGIC;814 p DescChain->cRefs = 1;815 p DescChain->uHeadIdx = uHeadIdx;816 *pp DescChain = pDescChain;757 PVIRTQBUF pVirtqBuf = (PVIRTQBUF)RTMemAllocZ(sizeof(VIRTQBUF_T)); 758 AssertReturn(pVirtqBuf, VERR_NO_MEMORY); 759 pVirtqBuf->u32Magic = VIRTQBUF_MAGIC; 760 pVirtqBuf->cRefs = 1; 761 pVirtqBuf->uHeadIdx = uHeadIdx; 762 *ppVirtqBuf = pVirtqBuf; 817 763 818 764 /* … … 825 771 uint32_t cSegsIn = 0; 826 772 uint32_t cSegsOut = 0; 827 PVIRTIOSGSEG paSegsIn = p DescChain->aSegsIn;828 PVIRTIOSGSEG paSegsOut = p DescChain->aSegsOut;773 PVIRTIOSGSEG paSegsIn = pVirtqBuf->aSegsIn; 774 PVIRTIOSGSEG paSegsOut = pVirtqBuf->aSegsOut; 829 775 830 776 do … … 853 799 RT_UNTRUSTED_VALIDATED_FENCE(); 854 800 855 virtioReadDesc(pDevIns, pVirtio, idxVirtq, uDescIdx, &desc);801 virtioReadDesc(pDevIns, pVirtio, uVirtqNbr, uDescIdx, &desc); 856 802 857 803 if (desc.fFlags & VIRTQ_DESC_F_WRITE) 858 804 { 859 Log6Func(("%s IN desc_idx=%u seg=%u addr=%RGp cb=%u\n", VIRTQNAME(pVirtio, idxVirtq), uDescIdx, cSegsIn, desc.GCPhysBuf, desc.cb));805 Log6Func(("%s IN desc_idx=%u seg=%u addr=%RGp cb=%u\n", VIRTQNAME(pVirtio, uVirtqNbr), uDescIdx, cSegsIn, desc.GCPhysBuf, desc.cb)); 860 806 cbIn += desc.cb; 861 807 pSeg = &paSegsIn[cSegsIn++]; … … 863 809 else 864 810 { 865 Log6Func(("%s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n", VIRTQNAME(pVirtio, idxVirtq), uDescIdx, cSegsOut, desc.GCPhysBuf, desc.cb));811 Log6Func(("%s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n", VIRTQNAME(pVirtio, uVirtqNbr), uDescIdx, cSegsOut, desc.GCPhysBuf, desc.cb)); 866 812 cbOut += desc.cb; 867 813 pSeg = &paSegsOut[cSegsOut++]; … … 884 830 if (cSegsIn) 885 831 { 886 virtioCoreSgBufInit(&p DescChain->SgBufIn, paSegsIn, cSegsIn);887 p DescChain->pSgPhysReturn = &pDescChain->SgBufIn;888 p DescChain->cbPhysReturn = cbIn;832 virtioCoreSgBufInit(&pVirtqBuf->SgBufIn, paSegsIn, cSegsIn); 833 pVirtqBuf->pSgPhysReturn = &pVirtqBuf->SgBufIn; 834 pVirtqBuf->cbPhysReturn = cbIn; 889 835 STAM_REL_COUNTER_ADD(&pVirtio->StatDescChainsSegsIn, cSegsIn); 890 836 } … … 892 838 if (cSegsOut) 893 839 { 894 virtioCoreSgBufInit(&p DescChain->SgBufOut, paSegsOut, cSegsOut);895 p DescChain->pSgPhysSend = &pDescChain->SgBufOut;896 p DescChain->cbPhysSend = cbOut;840 virtioCoreSgBufInit(&pVirtqBuf->SgBufOut, paSegsOut, cSegsOut); 841 pVirtqBuf->pSgPhysSend = &pVirtqBuf->SgBufOut; 842 pVirtqBuf->cbPhysSend = cbOut; 897 843 STAM_REL_COUNTER_ADD(&pVirtio->StatDescChainsSegsOut, cSegsOut); 898 844 } … … 904 850 } 905 851 906 907 /** 908 * Retains a reference to the given descriptor chain. 909 * 910 * @returns New reference count. 911 * @retval UINT32_MAX on invalid parameter. 912 * @param pDescChain The descriptor chain to reference. 913 */ 914 uint32_t virtioCoreR3DescChainRetain(PVIRTIO_DESC_CHAIN_T pDescChain) 915 { 916 AssertReturn(pDescChain, UINT32_MAX); 917 AssertReturn(pDescChain->u32Magic == VIRTIO_DESC_CHAIN_MAGIC, UINT32_MAX); 918 uint32_t cRefs = ASMAtomicIncU32(&pDescChain->cRefs); 852 /** API Function: See header file */ 853 uint32_t virtioCoreR3VirtqBufRetain(PVIRTQBUF pVirtqBuf) 854 { 855 AssertReturn(pVirtqBuf, UINT32_MAX); 856 AssertReturn(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC, UINT32_MAX); 857 uint32_t cRefs = ASMAtomicIncU32(&pVirtqBuf->cRefs); 919 858 Assert(cRefs > 1); 920 859 Assert(cRefs < 16); … … 923 862 924 863 925 /** 926 * Releases a reference to the given descriptor chain. 927 * 928 * @returns New reference count. 929 * @retval 0 if freed or invalid parameter. 930 * @param pVirtio Pointer to the shared virtio state. 931 * @param pDescChain The descriptor chain to reference. NULL is quietly 932 * ignored (returns 0). 933 */ 934 uint32_t virtioCoreR3DescChainRelease(PVIRTIOCORE pVirtio, PVIRTIO_DESC_CHAIN_T pDescChain) 935 { 936 if (!pDescChain) 864 /** API Function: See header file */ 865 uint32_t virtioCoreR3VirtqBufRelease(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf) 866 { 867 if (!pVirtqBuf) 937 868 return 0; 938 AssertReturn(p DescChain, 0);939 AssertReturn(p DescChain->u32Magic == VIRTIO_DESC_CHAIN_MAGIC, 0);940 uint32_t cRefs = ASMAtomicDecU32(&p DescChain->cRefs);869 AssertReturn(pVirtqBuf, 0); 870 AssertReturn(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC, 0); 871 uint32_t cRefs = ASMAtomicDecU32(&pVirtqBuf->cRefs); 941 872 Assert(cRefs < 16); 942 873 if (cRefs == 0) 943 874 { 944 p DescChain->u32Magic = ~VIRTIO_DESC_CHAIN_MAGIC;945 RTMemFree(p DescChain);875 pVirtqBuf->u32Magic = ~VIRTQBUF_MAGIC; 876 RTMemFree(pVirtqBuf); 946 877 STAM_REL_COUNTER_INC(&pVirtio->StatDescChainsFreed); 947 878 } … … 949 880 } 950 881 951 952 /* 953 * Notifies guest (via ISR or MSI-X) of device configuration change 954 * 955 * @param pVirtio Pointer to the shared virtio state. 956 */ 882 /** API Function: See header file */ 957 883 void virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio) 958 884 { … … 960 886 } 961 887 962 /** 963 * Enable or Disable notification for the specified queue 964 * 965 * @param pVirtio Pointer to the shared virtio state. 966 * @param idxVirtq Virtq number 967 * @param fEnable Selects notification mode (enabled or disabled) 968 */ 969 void virtioCoreVirtqNotifyEnable(PVIRTIOCORE pVirtio, uint16_t idxVirtq, bool fEnable) 888 void virtioCoreVirtqEnableNotify(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, bool fEnable) 970 889 { 971 890 if (pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK) 972 891 { 973 uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, idxVirtq);892 uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, uVirtqNbr); 974 893 975 894 if (fEnable) … … 978 897 fFlags |= VIRTQ_USED_F_NO_NOTIFY; 979 898 980 virtioWriteUsedRingFlags(pVirtio->pDevInsR3, pVirtio, idxVirtq, fFlags); 981 } 982 } 983 984 /** 985 * Initiate orderly reset procedure. This is an exposed API for clients that might need it. 986 * Invoked by client to reset the device and driver (see VirtIO 1.0 section 2.1.1/2.1.2) 987 * 988 * @param pVirtio Pointer to the virtio state. 989 */ 899 virtioWriteUsedRingFlags(pVirtio->pDevInsR3, pVirtio, uVirtqNbr, fFlags); 900 } 901 } 902 903 /** API function: See Header file */ 990 904 void virtioCoreResetAll(PVIRTIOCORE pVirtio) 991 905 { … … 999 913 } 1000 914 1001 /** 1002 * Fetches descriptor chain using avail ring of indicated queue and converts the descriptor 1003 * chain into its OUT (to device) and IN to guest components, but does NOT remove it from 1004 * the 'avail' queue. I.e. doesn't advance the index. This can be used with virtioVirtqSkip(), 1005 * which *does* advance the avail index. Together they facilitate a mechanism that allows 1006 * work with a queue element (descriptor chain) to be aborted if necessary, by not advancing 1007 * the pointer, or, upon success calling the skip function (above) to move to the next element. 1008 * 1009 * Additionally it converts the OUT desc chain data to a contiguous virtual 1010 * memory buffer for easy consumption by the caller. The caller must return the 1011 * descriptor chain pointer via virtioCoreR3VirtqPut() and then call virtioCoreVirtqSync() 1012 * at some point to return the data to the guest and complete the transaction. 1013 * 1014 * @param pDevIns The device instance. 1015 * @param pVirtio Pointer to the shared virtio state. 1016 * @param idxVirtq Virtq number 1017 * @param ppDescChain Address to store pointer to descriptor chain that contains the 1018 * pre-processed transaction information pulled from the virtq. 1019 * 1020 * @returns VBox status code: 1021 * @retval VINF_SUCCESS Success 1022 * @retval VERR_INVALID_STATE VirtIO not in ready state (asserted). 1023 * @retval VERR_NOT_AVAILABLE If the queue is empty. 1024 */ 1025 1026 int virtioCoreR3VirtqPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, 1027 PPVIRTIO_DESC_CHAIN_T ppDescChain) 1028 { 1029 return virtioCoreR3VirtqGet(pDevIns, pVirtio, idxVirtq, ppDescChain, false); 1030 } 1031 1032 /** 1033 * Skip the next entry in the specified queue (typically used with virtioCoreR3VirtqPeek()) 1034 * 1035 * @param pVirtio Pointer to the virtio state. 1036 * @param idxVirtq Index of queue 1037 */ 1038 int virtioCoreR3VirtqSkip(PVIRTIOCORE pVirtio, uint16_t idxVirtq) 1039 { 1040 Assert(idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState)); 1041 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq]; 1042 1043 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[idxVirtq], 915 /** API function: See Header file */ 916 int virtioCoreR3VirtqBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, 917 PPVIRTQBUF ppVirtqBuf) 918 { 919 return virtioCoreR3VirtqBufGet(pDevIns, pVirtio, uVirtqNbr, ppVirtqBuf, false); 920 } 921 922 /** API function: See Header file */ 923 int virtioCoreR3VirtqBufSkip(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 924 { 925 Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 926 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 927 928 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[uVirtqNbr], 1044 929 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 1045 930 … … 1053 938 } 1054 939 1055 /** 1056 * Fetches descriptor chain using avail ring of indicated queue and converts the descriptor 1057 * chain into its OUT (to device) and IN to guest components. 1058 * 1059 * Additionally it converts the OUT desc chain data to a contiguous virtual 1060 * memory buffer for easy consumption by the caller. The caller must return the 1061 * descriptor chain pointer via virtioCoreR3VirtqPut() and then call virtioCoreVirtqSync() 1062 * at some point to return the data to the guest and complete the transaction. 1063 * 1064 * @param pDevIns The device instance. 1065 * @param pVirtio Pointer to the shared virtio state. 1066 * @param idxVirtq Virtq number 1067 * @param ppDescChain Address to store pointer to descriptor chain that contains the 1068 * pre-processed transaction information pulled from the virtq. 1069 * Returned reference must be released by calling 1070 * virtioCoreR3DescChainRelease(). 1071 * @param fRemove flags whether to remove desc chain from queue (false = peek) 1072 * 1073 * @returns VBox status code: 1074 * @retval VINF_SUCCESS Success 1075 * @retval VERR_INVALID_STATE VirtIO not in ready state (asserted). 1076 * @retval VERR_NOT_AVAILABLE If the queue is empty. 1077 */ 1078 int virtioCoreR3VirtqGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, 1079 PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove) 1080 { 1081 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq]; 940 /** API function: See Header file */ 941 int virtioCoreR3VirtqBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, 942 PPVIRTQBUF ppVirtqBuf, bool fRemove) 943 { 944 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 1082 945 1083 946 if (IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtqState)) 1084 947 return VERR_NOT_AVAILABLE; 1085 948 1086 uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, idxVirtq, pVirtqState->uAvailIdxShadow);949 uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, uVirtqNbr, pVirtqState->uAvailIdxShadow); 1087 950 1088 951 if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX) 1089 virtioWriteUsedAvailEvent(pDevIns,pVirtio, idxVirtq, pVirtqState->uAvailIdxShadow + 1);952 virtioWriteUsedAvailEvent(pDevIns,pVirtio, uVirtqNbr, pVirtqState->uAvailIdxShadow + 1); 1090 953 1091 954 if (fRemove) 1092 955 pVirtqState->uAvailIdxShadow++; 1093 956 1094 int rc = virtioCoreR3 DescChainGet(pDevIns, pVirtio, idxVirtq, uHeadIdx, ppDescChain);957 int rc = virtioCoreR3VirtqBufGet(pDevIns, pVirtio, uVirtqNbr, uHeadIdx, ppVirtqBuf); 1095 958 return rc; 1096 959 } 1097 960 1098 /** 1099 * Returns data to the guest to complete a transaction initiated by virtVirtqGet(). 1100 * 1101 * The caller passes in a pointer to a scatter-gather buffer of virtual memory segments 1102 * and a pointer to the descriptor chain context originally derived from the pulled 1103 * queue entry, and this function will write the virtual memory s/g buffer into the 1104 * guest's physical memory free the descriptor chain. The caller handles the freeing 1105 * (as needed) of the virtual memory buffer. 1106 * 1107 * @note This does a write-ahead to the used ring of the guest's queue. The data 1108 * written won't be seen by the guest until the next call to virtioCoreVirtqSync() 1109 * 1110 * 1111 * @param pDevIns The device instance (for reading). 1112 * @param pVirtio Pointer to the shared virtio state. 1113 * @param idxVirtq Virtq number 1114 * 1115 * @param pSgVirtReturn Points to scatter-gather buffer of virtual memory 1116 * segments the caller is returning to the guest. 1117 * 1118 * @param pDescChain This contains the context of the scatter-gather 1119 * buffer originally pulled from the queue. 1120 * 1121 * @param fFence If true, put up copy fence (memory barrier) after 1122 * copying to guest phys. mem. 1123 * 1124 * @returns VBox status code. 1125 * @retval VINF_SUCCESS Success 1126 * @retval VERR_INVALID_STATE VirtIO not in ready state 1127 * @retval VERR_NOT_AVAILABLE Virtq is empty 1128 * 1129 * @note This function will not release any reference to pDescChain. The 1130 * caller must take care of that. 1131 */ 1132 int virtioCoreR3VirtqPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, PRTSGBUF pSgVirtReturn, 1133 PVIRTIO_DESC_CHAIN_T pDescChain, bool fFence) 1134 { 1135 Assert(idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState)); 1136 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq]; 1137 PVIRTIOSGBUF pSgPhysReturn = pDescChain->pSgPhysReturn; 1138 1139 Assert(pDescChain->u32Magic == VIRTIO_DESC_CHAIN_MAGIC); 1140 Assert(pDescChain->cRefs > 0); 961 /** API function: See Header file */ 962 int virtioCoreR3VirtqBufPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, PRTSGBUF pSgVirtReturn, 963 PVIRTQBUF pVirtqBuf, bool fFence) 964 { 965 Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 966 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 967 PVIRTIOSGBUF pSgPhysReturn = pVirtqBuf->pSgPhysReturn; 968 969 Assert(pVirtqBuf->u32Magic == VIRTQBUF_MAGIC); 970 Assert(pVirtqBuf->cRefs > 0); 1141 971 1142 972 AssertMsgReturn(IS_DRIVER_OK(pVirtio), ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 1143 973 1144 974 Log6Func(("Copying client data to %s, desc chain (head desc_idx %d)\n", 1145 VIRTQNAME(pVirtio, idxVirtq), virtioReadUsedRingIdx(pDevIns, pVirtio, idxVirtq)));975 VIRTQNAME(pVirtio, uVirtqNbr), virtioReadUsedRingIdx(pDevIns, pVirtio, uVirtqNbr))); 1146 976 1147 977 /* Copy s/g buf (virtual memory) to guest phys mem (IN direction). */ … … 1173 1003 /* If this write-ahead crosses threshold where the driver wants to get an event flag it */ 1174 1004 if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX) 1175 if (pVirtqState->uUsedIdxShadow == virtioReadAvailUsedEvent(pDevIns, pVirtio, idxVirtq))1005 if (pVirtqState->uUsedIdxShadow == virtioReadAvailUsedEvent(pDevIns, pVirtio, uVirtqNbr)) 1176 1006 pVirtqState->fVirtqRingEventThreshold = true; 1177 1007 … … 1179 1009 * Place used buffer's descriptor in used ring but don't update used ring's slot index. 1180 1010 * That will be done with a subsequent client call to virtioCoreVirtqSync() */ 1181 virtioWriteUsedElem(pDevIns, pVirtio, idxVirtq, pVirtqState->uUsedIdxShadow++, pDescChain->uHeadIdx, (uint32_t)cbTotal);1011 virtioWriteUsedElem(pDevIns, pVirtio, uVirtqNbr, pVirtqState->uUsedIdxShadow++, pVirtqBuf->uHeadIdx, (uint32_t)cbTotal); 1182 1012 1183 1013 if (pSgVirtReturn) 1184 1014 Log6Func((".... Copied %zu bytes in %d segs to %u byte buffer, residual=%zu\n", 1185 cbTotal - cbRemain, pSgVirtReturn->cSegs, p DescChain->cbPhysReturn, pDescChain->cbPhysReturn - cbTotal));1015 cbTotal - cbRemain, pSgVirtReturn->cSegs, pVirtqBuf->cbPhysReturn, pVirtqBuf->cbPhysReturn - cbTotal)); 1186 1016 1187 1017 Log6Func(("Write ahead used_idx=%u, %s used_idx=%u\n", 1188 pVirtqState->uUsedIdxShadow, VIRTQNAME(pVirtio, idxVirtq), virtioReadUsedRingIdx(pDevIns, pVirtio, idxVirtq)));1018 pVirtqState->uUsedIdxShadow, VIRTQNAME(pVirtio, uVirtqNbr), virtioReadUsedRingIdx(pDevIns, pVirtio, uVirtqNbr))); 1189 1019 1190 1020 return VINF_SUCCESS; … … 1193 1023 #endif /* IN_RING3 */ 1194 1024 1025 /** API function: See Header file */ 1026 int virtioCoreVirtqSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 1027 { 1028 Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 1029 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 1030 1031 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[uVirtqNbr], 1032 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 1033 1034 Log6Func(("Updating %s used_idx to %u\n", 1035 VIRTQNAME(pVirtio, uVirtqNbr), pVirtqState->uUsedIdxShadow)); 1036 1037 virtioWriteUsedRingIdx(pDevIns, pVirtio, uVirtqNbr, pVirtqState->uUsedIdxShadow); 1038 virtioCoreNotifyGuestDriver(pDevIns, pVirtio, uVirtqNbr); 1039 1040 return VINF_SUCCESS; 1041 } 1042 1043 1195 1044 /** 1196 * Updates the indicated virtq's "used ring" descriptor index to match the 1197 * current write-head index, thus exposing the data added to the used ring by all 1198 * virtioCoreR3VirtqPut() calls since the last sync. This should be called after one or 1199 * more virtioCoreR3VirtqPut() calls to inform the guest driver there is data in the queue. 1200 * Explicit notifications (e.g. interrupt or MSI-X) will be sent to the guest, 1201 * depending on VirtIO features negotiated and conditions, otherwise the guest 1202 * will detect the update by polling. (see VirtIO 1.0 specification, Section 2.4 "Virtqueues"). 1203 * 1204 * @param pDevIns The device instance. 1205 * @param pVirtio Pointer to the shared virtio state. 1206 * @param idxVirtq Virtq number 1207 * 1208 * @returns VBox status code. 1209 * @retval VINF_SUCCESS Success 1210 * @retval VERR_INVALID_STATE VirtIO not in ready state 1211 */ 1212 int virtioCoreVirtqSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq) 1213 { 1214 Assert(idxVirtq < RT_ELEMENTS(pVirtio->aVirtqState)); 1215 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[idxVirtq]; 1216 1217 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[idxVirtq], 1218 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 1219 1220 Log6Func(("Updating %s used_idx to %u\n", 1221 VIRTQNAME(pVirtio, idxVirtq), pVirtqState->uUsedIdxShadow)); 1222 1223 virtioWriteUsedRingIdx(pDevIns, pVirtio, idxVirtq, pVirtqState->uUsedIdxShadow); 1224 virtioCoreNotifyGuestDriver(pDevIns, pVirtio, idxVirtq); 1225 1226 return VINF_SUCCESS; 1227 } 1228 1229 1230 /** 1231 */ 1232 static void virtioCoreVirtqNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, uint16_t uNotifyIdx) 1045 */ 1046 static void virtioCoreVirtqNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint16_t uNotifyIdx) 1233 1047 { 1234 1048 1235 1049 PVIRTIOCORECC pVirtioCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOCORECC); 1236 1050 1237 /* See VirtIO 1.0, section 4.1.5.2 It implies that idxVirtqand uNotifyIdx should match.1051 /* See VirtIO 1.0, section 4.1.5.2 It implies that uVirtqNbr and uNotifyIdx should match. 1238 1052 * Disregarding this notification may cause throughput to stop, however there's no way to know 1239 1053 * which was queue was intended for wake-up if the two parameters disagree. */ 1240 1054 1241 AssertMsg(uNotifyIdx == idxVirtq,1055 AssertMsg(uNotifyIdx == uVirtqNbr, 1242 1056 ("Guest kicked virtq %d's notify addr w/non-corresponding virtq idx %d\n", 1243 idxVirtq, uNotifyIdx));1057 uVirtqNbr, uNotifyIdx)); 1244 1058 RT_NOREF(uNotifyIdx); 1245 1059 1246 AssertReturnVoid( idxVirtq< RT_ELEMENTS(pVirtio->aVirtqState));1060 AssertReturnVoid(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 1247 1061 Log6Func(("%s (desc chains: %u)\n", 1248 pVirtio->aVirtqState[ idxVirtq].szVirtqName,1249 virtioCoreVirtqAvailCount(pDevIns, pVirtio, idxVirtq)));1062 pVirtio->aVirtqState[uVirtqNbr].szVirtqName, 1063 virtioCoreVirtqAvailCount(pDevIns, pVirtio, uVirtqNbr))); 1250 1064 1251 1065 /* Inform client */ 1252 pVirtioCC->pfnVirtqNotified(pDevIns, pVirtio, idxVirtq);1066 pVirtioCC->pfnVirtqNotified(pDevIns, pVirtio, uVirtqNbr); 1253 1067 } 1254 1068 … … 1262 1076 * @param pDevIns The device instance. 1263 1077 * @param pVirtio Pointer to the shared virtio state. 1264 * @param idxVirtqVirtq to check for guest interrupt handling preference1265 */ 1266 static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq)1267 { 1268 1269 Assert( idxVirtq< RT_ELEMENTS(pVirtio->aVirtqState));1270 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[ idxVirtq];1078 * @param uVirtqNbr Virtq to check for guest interrupt handling preference 1079 */ 1080 static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 1081 { 1082 1083 Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 1084 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 1271 1085 1272 1086 if (!IS_DRIVER_OK(pVirtio)) … … 1282 1096 #ifdef IN_RING3 1283 1097 Log6Func(("...kicking guest %s, VIRTIO_F_EVENT_IDX set and threshold (%d) reached\n", 1284 VIRTQNAME(pVirtio, idxVirtq), (uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxVirtq)));1098 VIRTQNAME(pVirtio, uVirtqNbr), (uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, uVirtqNbr))); 1285 1099 #endif 1286 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uVirtqMsixVector[ idxVirtq]);1100 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uVirtqMsixVector[uVirtqNbr]); 1287 1101 pVirtqState->fVirtqRingEventThreshold = false; 1288 1102 return; … … 1290 1104 #ifdef IN_RING3 1291 1105 Log6Func(("...skip interrupt %s, VIRTIO_F_EVENT_IDX set but threshold (%d) not reached (%d)\n", 1292 VIRTQNAME(pVirtio, idxVirtq),(uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxVirtq), pVirtqState->uUsedIdxShadow));1106 VIRTQNAME(pVirtio, uVirtqNbr),(uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, uVirtqNbr), pVirtqState->uUsedIdxShadow)); 1293 1107 #endif 1294 1108 } … … 1296 1110 { 1297 1111 /** If guest driver hasn't suppressed interrupts, interrupt */ 1298 if (!(virtioReadAvailRingFlags(pDevIns, pVirtio, idxVirtq) & VIRTQ_AVAIL_F_NO_INTERRUPT))1299 { 1300 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uVirtqMsixVector[ idxVirtq]);1112 if (!(virtioReadAvailRingFlags(pDevIns, pVirtio, uVirtqNbr) & VIRTQ_AVAIL_F_NO_INTERRUPT)) 1113 { 1114 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uVirtqMsixVector[uVirtqNbr]); 1301 1115 return; 1302 1116 } 1303 1117 Log6Func(("...skipping interrupt for %s (guest set VIRTQ_AVAIL_F_NO_INTERRUPT)\n", 1304 VIRTQNAME(pVirtio, idxVirtq)));1118 VIRTQNAME(pVirtio, uVirtqNbr))); 1305 1119 } 1306 1120 } … … 1347 1161 1348 1162 #ifdef IN_RING3 1349 static void virtioResetVirtq(PVIRTIOCORE pVirtio, uint16_t idxVirtq)1350 { 1351 Assert( idxVirtq< RT_ELEMENTS(pVirtio->aVirtqState));1352 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[ idxVirtq];1163 static void virtioResetVirtq(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 1164 { 1165 Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 1166 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 1353 1167 pVirtqState->uAvailIdxShadow = 0; 1354 1168 pVirtqState->uUsedIdxShadow = 0; 1355 1169 pVirtqState->fVirtqRingEventThreshold = false; 1356 pVirtio->uVirtqEnable[ idxVirtq] = false;1357 pVirtio->uVirtqSize[ idxVirtq] = VIRTQ_MAX_ENTRIES;1358 pVirtio->uVirtqNotifyOff[ idxVirtq] = idxVirtq;1359 pVirtio->uVirtqMsixVector[ idxVirtq] = idxVirtq+ 2;1170 pVirtio->uVirtqEnable[uVirtqNbr] = false; 1171 pVirtio->uVirtqSize[uVirtqNbr] = VIRTQ_MAX_ENTRIES; 1172 pVirtio->uVirtqNotifyOff[uVirtqNbr] = uVirtqNbr; 1173 pVirtio->uVirtqMsixVector[uVirtqNbr] = uVirtqNbr + 2; 1360 1174 if (!pVirtio->fMsiSupport) /* VirtIO 1.0, 4.1.4.3 and 4.1.5.1.2 */ 1361 pVirtio->uVirtqMsixVector[ idxVirtq] = VIRTIO_MSI_NO_VECTOR;1362 1363 virtioLowerInterrupt(pVirtio->pDevInsR3, pVirtio->uVirtqMsixVector[ idxVirtq]);1175 pVirtio->uVirtqMsixVector[uVirtqNbr] = VIRTIO_MSI_NO_VECTOR; 1176 1177 virtioLowerInterrupt(pVirtio->pDevInsR3, pVirtio->uVirtqMsixVector[uVirtqNbr]); 1364 1178 } 1365 1179 … … 1388 1202 pVirtio->uMsixConfig = VIRTIO_MSI_NO_VECTOR; 1389 1203 1390 for (uint16_t idxVirtq = 0; idxVirtq < VIRTQ_MAX_CNT; idxVirtq++)1391 virtioResetVirtq(pVirtio, idxVirtq);1204 for (uint16_t uVirtqNbr = 0; uVirtqNbr < VIRTQ_MAX_CNT; uVirtqNbr++) 1205 virtioResetVirtq(pVirtio, uVirtqNbr); 1392 1206 } 1393 1207 … … 2026 1840 break; 2027 1841 case kvirtIoVmStateChangedResume: 2028 virtioCoreNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, 0 /* idxVirtq*/);1842 virtioCoreNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, 0 /* uVirtqNbr */); 2029 1843 break; 2030 1844 default: -
trunk/src/VBox/Devices/VirtIO/VirtioCore.h
r84818 r84819 1 1 /* $Id$ */ 2 2 3 /** @file 3 * Virtio _1_0.h - Virtio Declarations4 * VirtioCore.h - Virtio Declarations 4 5 */ 5 6 … … 93 94 94 95 /** 95 * Virtio descriptor chain representation. 96 */ 97 typedef struct VIRTIO_DESC_CHAIN 98 { 99 uint32_t u32Magic; /**< Magic value, VIRTIO_DESC_CHAIN_MAGIC. */ 96 * VirtIO buffers are actually descriptor chains. VirtIO's scatter-gather architecture 97 * defines a head descriptor (index into ring of descriptors), which is chained to 0 or more 98 * other descriptors that can optionally continue the chain. This structure is VirtualBox's 99 * Virtq buffer representation, which contains a reference to the head desc chain idx and 100 * context for working with virtq buffers. 101 */ 102 typedef struct VIRTQBUF 103 { 104 uint32_t u32Magic; /**< Magic value, VIRTQBUF_MAGIC. */ 100 105 uint32_t volatile cRefs; /**< Reference counter. */ 101 106 uint32_t uHeadIdx; /**< Head idx of associated desc chain */ … … 112 117 VIRTIOSGSEG aSegsOut[VIRTQ_MAX_ENTRIES]; 113 118 /** @} */ 114 } VIRTIO_DESC_CHAIN_T; 115 /** Pointer to a Virtio descriptor chain. */ 116 typedef VIRTIO_DESC_CHAIN_T *PVIRTIO_DESC_CHAIN_T; 117 /** Pointer to a Virtio descriptor chain pointer. */ 118 typedef VIRTIO_DESC_CHAIN_T **PPVIRTIO_DESC_CHAIN_T; 119 /** Magic value for VIRTIO_DESC_CHAIN_T::u32Magic. */ 120 #define VIRTIO_DESC_CHAIN_MAGIC UINT32_C(0x19600219) 119 } VIRTQBUF_T; 120 121 /** Pointers to a Virtio descriptor chain. */ 122 typedef VIRTQBUF_T *PVIRTQBUF, **PPVIRTQBUF; 123 /** Magic value for VIRTQBUF_T::u32Magic. */ 124 #define VIRTQBUF_MAGIC UINT32_C(0x19600219) 121 125 122 126 typedef struct VIRTIOPCIPARAMS … … 187 191 typedef struct VIRTQSTATE 188 192 { 189 uint16_t idxVirtq; /**< Index of this queue */193 uint16_t uVirtqNbr; /**< Index of this queue */ 190 194 char szVirtqName[32]; /**< Dev-specific name of queue */ 191 195 uint16_t uAvailIdxShadow; /**< Consumer's position in avail ring */ … … 348 352 * @param pVirtio Pointer to the shared virtio state. 349 353 * @param pVirtioCC Pointer to the ring-3 virtio state. 350 * @param idxVirtqIndex of the notified queue354 * @param uVirtqNbr Index of the notified queue 351 355 */ 352 DECLCALLBACKMEMBER(void, pfnVirtqNotified)(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq);356 DECLCALLBACKMEMBER(void, pfnVirtqNotified)(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr); 353 357 354 358 /** @} */ … … 381 385 * @param pVirtio Pointer to the shared virtio state. 382 386 * @param pVirtioCC Pointer to the ring-3 virtio state. 383 * @param idxVirtqIndex of the notified queue387 * @param uVirtqNbr Index of the notified queue 384 388 */ 385 DECLCALLBACKMEMBER(void, pfnVirtqNotified)(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq);389 DECLCALLBACKMEMBER(void, pfnVirtqNotified)(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr); 386 390 387 391 } VIRTIOCORER0; … … 405 409 * @{ */ 406 410 407 int virtioCoreVirtqSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq); 408 uint16_t virtioCoreVirtqAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq); 409 void virtioCoreVirtqEnable(PVIRTIOCORE pVirtio, uint16_t idxVirtq, bool fEnable); 410 void virtioCoreVirtqNotifyEnable(PVIRTIOCORE pVirtio, uint16_t idxVirtq, bool fEnable); 411 412 /** 413 * Initiate orderly reset procedure. This is an exposed API for clients that might need it. 414 * Invoked by client to reset the device and driver (see VirtIO 1.0 section 2.1.1/2.1.2) 415 * 416 * @param pVirtio Pointer to the virtio state. 417 */ 418 void virtioCoreResetAll(PVIRTIOCORE pVirtio); 419 420 /** 421 * 'Attaches' the inheriting device-specific code's queue state to the VirtIO core 422 * queue management, informing the core of the name of the queue and number. The VirtIO core 423 * allocates the queue state information so it can handle all the core VirtiIO queue operations 424 * and dispatch callbacks, etc... 425 * 426 * @param pVirtio Pointer to the shared virtio state. 427 * @param uVirtqNbr Virtq number 428 * @param pcszName Name to give queue 429 * 430 * @returns VBox status code. 431 */ 432 int virtioCoreR3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, const char *pcszName); 433 434 /** 435 * Enables or disables a virtq 436 * 437 * @param pVirtio Pointer to the shared virtio state. 438 * @param uVirtqNbr Virtq number 439 * @param fEnable Flags whether to enable or disable the virtq 440 * 441 */ 442 443 void virtioCoreVirtqEnable(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, bool fEnable); 444 445 /** 446 * Enable or Disable notification for the specified queue 447 * 448 * @param pVirtio Pointer to the shared virtio state. 449 * @param uVirtqNbr Virtq number 450 * @param fEnable Selects notification mode (enabled or disabled) 451 */ 452 void virtioCoreVirtqEnableNotify(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, bool fEnable); 453 454 /* 455 * Notifies guest (via ISR or MSI-X) of device configuration change 456 * 457 * @param pVirtio Pointer to the shared virtio state. 458 */ 411 459 void virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio); 412 void virtioCoreResetAll(PVIRTIOCORE pVirtio); 460 461 /* 462 * Displays the VirtIO spec-related features offered by the core component, 463 * as well as which features have been negotiated and accepted or declined by the guest driver, 464 * providing a summary view of the configuration the device is operating with. 465 * 466 * @param pVirtio Pointer to the shared virtio state. 467 * @param pHlp Pointer to the debug info hlp struct 468 */ 413 469 void virtioCorePrintFeatures(VIRTIOCORE *pVirtio, PCDBGFINFOHLP pHlp); 414 470 415 uint32_t virtioCoreR3DescChainRetain(PVIRTIO_DESC_CHAIN_T pDescChain); 416 uint32_t virtioCoreR3DescChainRelease(PVIRTIOCORE pVirtio, PVIRTIO_DESC_CHAIN_T pDescChain); 417 void virtioCoreR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs); 418 void virtioCoreR3VirtqInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int idxVirtq); 419 int virtioCoreR3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t idxVirtq, const char *pcszName); 420 421 int virtioCoreR3DescChainGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, 422 uint16_t uHeadIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain); 423 424 int virtioCoreR3VirtqPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, 425 PPVIRTIO_DESC_CHAIN_T ppDescChain); 426 427 int virtioCoreR3VirtqSkip(PVIRTIOCORE pVirtio, uint16_t idxVirtq); 428 429 int virtioCoreR3VirtqGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, 430 PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove); 431 432 int virtioCoreR3VirtqPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq, PRTSGBUF pSgVirtReturn, 433 PVIRTIO_DESC_CHAIN_T pDescChain, bool fFence); 434 471 /* 472 * Debuging assist feature displays the state of the VirtIO core code, which includes 473 * an overview of the state of all of the queues. 474 * 475 * This can be invoked when running the VirtualBox debugger, or from the command line 476 * using the command: "VboxManage debugvm <VM name or id> info <device name> [args]" 477 * 478 * Example: VBoxManage debugvm myVnetVm info "virtio-net" all 479 * 480 * This is implemented currently to be invoked by the inheriting device-specific code 481 * (see DevVirtioNet for an example, which receives the debugvm command directly). 482 * That devices lists the available sub-options if no arguments are provided. In that 483 * example this virtq info related function is invoked hierarchically when virtio-net 484 * displays its device-specific queue info. 485 * 486 * @param pDevIns The device instance. 487 * @param pHlp Pointer to the debug info hlp struct 488 * @param pszArgs Arguments to function 489 */ 490 void virtioCoreR3VirtqInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int uVirtqNbr); 491 492 /* 493 * Returns the number of avail bufs in the virtq. 494 * 495 * @param pDevIns The device instance. 496 * @param pVirtio Pointer to the shared virtio state. 497 * @param uVirtqNbr Virtqueue to return the count of buffers available for. 498 */ 499 uint16_t virtioCoreVirtqAvailCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr); 500 501 /** 502 * Fetches descriptor chain using avail ring of indicated queue and converts the descriptor 503 * chain into its OUT (to device) and IN to guest components, but does NOT remove it from 504 * the 'avail' queue. I.e. doesn't advance the index. This can be used with virtioVirtqSkip(), 505 * which *does* advance the avail index. Together they facilitate a mechanism that allows 506 * work with a queue element (descriptor chain) to be aborted if necessary, by not advancing 507 * the pointer, or, upon success calling the skip function (above) to move to the next element. 508 * 509 * Additionally it converts the OUT desc chain data to a contiguous virtual 510 * memory buffer for easy consumption by the caller. The caller must return the 511 * descriptor chain pointer via virtioCoreR3VirtqBufPut() and then call virtioCoreVirtqSync() 512 * at some point to return the data to the guest and complete the transaction. 513 * 514 * @param pDevIns The device instance. 515 * @param pVirtio Pointer to the shared virtio state. 516 * @param uVirtqNbr Virtq number 517 * @param ppVirtqBuf Address to store pointer to descriptor chain that contains the 518 * pre-processed transaction information pulled from the virtq. 519 * 520 * @returns VBox status code: 521 * @retval VINF_SUCCESS Success 522 * @retval VERR_INVALID_STATE VirtIO not in ready state (asserted). 523 * @retval VERR_NOT_AVAILABLE If the queue is empty. 524 */ 525 int virtioCoreR3VirtqBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, 526 PPVIRTQBUF ppVirtqBuf); 527 528 /** 529 * Fetches the next descriptor chain using avail ring of indicated queue and converts the descriptor 530 * chain into its OUT (to device) and IN to guest components. 531 * 532 * Additionally it converts the OUT desc chain data to a contiguous virtual 533 * memory buffer for easy consumption by the caller. The caller must return the 534 * descriptor chain pointer via virtioCoreR3VirtqBufPut() and then call virtioCoreVirtqSync() 535 * at some point to return the data to the guest and complete the transaction. 536 * 537 * @param pDevIns The device instance. 538 * @param pVirtio Pointer to the shared virtio state. 539 * @param uVirtqNbr Virtq number 540 * @param ppVirtqBuf Address to store pointer to descriptor chain that contains the 541 * pre-processed transaction information pulled from the virtq. 542 * Returned reference must be released by calling 543 * virtioCoreR3VirtqBufRelease(). 544 * @param fRemove flags whether to remove desc chain from queue (false = peek) 545 * 546 * @returns VBox status code: 547 * @retval VINF_SUCCESS Success 548 * @retval VERR_INVALID_STATE VirtIO not in ready state (asserted). 549 * @retval VERR_NOT_AVAILABLE If the queue is empty. 550 */ 551 int virtioCoreR3VirtqBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, 552 PPVIRTQBUF ppVirtqBuf, bool fRemove); 553 554 555 /** 556 * Fetches a specific descriptor chain using avail ring of indicated queue and converts the descriptor 557 * chain into its OUT (to device) and IN to guest components. 558 * 559 * Additionally it converts the OUT desc chain data to a contiguous virtual 560 * memory buffer for easy consumption by the caller. The caller must return the 561 * descriptor chain pointer via virtioCoreR3VirtqBufPut() and then call virtioCoreVirtqSync() 562 * at some point to return the data to the guest and complete the transaction. 563 * 564 * @param pDevIns The device instance. 565 * @param pVirtio Pointer to the shared virtio state. 566 * @param uVirtqNbr Virtq number 567 * @param ppVirtqBuf Address to store pointer to descriptor chain that contains the 568 * pre-processed transaction information pulled from the virtq. 569 * Returned reference must be released by calling 570 * virtioCoreR3VirtqBufRelease(). 571 * @param fRemove flags whether to remove desc chain from queue (false = peek) 572 * 573 * @returns VBox status code: 574 * @retval VINF_SUCCESS Success 575 * @retval VERR_INVALID_STATE VirtIO not in ready state (asserted). 576 * @retval VERR_NOT_AVAILABLE If the queue is empty. 577 */ 578 579 int virtioCoreR3VirtqBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, 580 uint16_t uHeadIdx, PPVIRTQBUF ppVirtqBuf); 581 582 /** 583 * Returns data to the guest to complete a transaction initiated by virtVirtqGet(). 584 * 585 * The caller passes in a pointer to a scatter-gather buffer of virtual memory segments 586 * and a pointer to the descriptor chain context originally derived from the pulled 587 * queue entry, and this function will write the virtual memory s/g buffer into the 588 * guest's physical memory free the descriptor chain. The caller handles the freeing 589 * (as needed) of the virtual memory buffer. 590 * 591 * @note This does a write-ahead to the used ring of the guest's queue. The data 592 * written won't be seen by the guest until the next call to virtioCoreVirtqSync() 593 * 594 * 595 * @param pDevIns The device instance (for reading). 596 * @param pVirtio Pointer to the shared virtio state. 597 * @param uVirtqNbr Virtq number 598 * 599 * @param pSgVirtReturn Points to scatter-gather buffer of virtual memory 600 * segments the caller is returning to the guest. 601 * 602 * @param pVirtqBuf This contains the context of the scatter-gather 603 * buffer originally pulled from the queue. 604 * 605 * @param fFence If true, put up copy fence (memory barrier) after 606 * copying to guest phys. mem. 607 * 608 * @returns VBox status code. 609 * @retval VINF_SUCCESS Success 610 * @retval VERR_INVALID_STATE VirtIO not in ready state 611 * @retval VERR_NOT_AVAILABLE Virtq is empty 612 * 613 * @note This function will not release any reference to pVirtqBuf. The 614 * caller must take care of that. 615 */ 616 617 int virtioCoreR3VirtqBufPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, PRTSGBUF pSgVirtReturn, 618 PVIRTQBUF pVirtqBuf, bool fFence); 619 620 /** 621 * Skip the next entry in the specified queue (typically used with virtioCoreR3VirtqBufPeek()) 622 * 623 * @param pVirtio Pointer to the virtio state. 624 * @param uVirtqNbr Index of queue 625 */ 626 int virtioCoreR3VirtqBufSkip(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr); 627 628 /** 629 * Updates the indicated virtq's "used ring" descriptor index to match the 630 * current write-head index, thus exposing the data added to the used ring by all 631 * virtioCoreR3VirtqBufPut() calls since the last sync. This should be called after one or 632 * more virtioCoreR3VirtqBufPut() calls to inform the guest driver there is data in the queue. 633 * Explicit notifications (e.g. interrupt or MSI-X) will be sent to the guest, 634 * depending on VirtIO features negotiated and conditions, otherwise the guest 635 * will detect the update by polling. (see VirtIO 1.0 specification, Section 2.4 "Virtqueues"). 636 * 637 * @param pDevIns The device instance. 638 * @param pVirtio Pointer to the shared virtio state. 639 * @param uVirtqNbr Virtq number 640 * 641 * @returns VBox status code. 642 * @retval VINF_SUCCESS Success 643 * @retval VERR_INVALID_STATE VirtIO not in ready state 644 */ 645 int virtioCoreVirtqSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr); 646 647 /** 648 * Retains a reference to the given descriptor chain. 649 * 650 * @returns New reference count. 651 * @retval UINT32_MAX on invalid parameter. 652 * @param pVirtqBuf The descriptor chain to reference. 653 */ 654 uint32_t virtioCoreR3VirtqBufRetain(PVIRTQBUF pVirtqBuf); 655 656 /** 657 * Releases a reference to the given descriptor chain. 658 * 659 * @returns New reference count. 660 * @retval 0 if freed or invalid parameter. 661 * @param pVirtio Pointer to the shared virtio state. 662 * @param pVirtqBuf The descriptor chain to reference. NULL is quietly 663 * ignored (returns 0). 664 */ 665 uint32_t virtioCoreR3VirtqBufRelease(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf); 435 666 436 667 /** … … 438 669 * 439 670 * @param pVirtio Pointer to the virtio state. 440 * @param idxVirtqVirtq number.441 * @returns 442 */ 443 DECLINLINE(bool) virtioCoreIsVirtqEnabled(PVIRTIOCORE pVirtio, uint16_t idxVirtq)444 { 445 Assert( idxVirtq< RT_ELEMENTS(pVirtio->aVirtqState));446 return pVirtio->uVirtqEnable[ idxVirtq] != 0;671 * @param uVirtqNbr Virtq number. 672 * @returns true or false indicating whether to enable queue or not 673 */ 674 DECLINLINE(bool) virtioCoreIsVirtqEnabled(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 675 { 676 Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 677 return pVirtio->uVirtqEnable[uVirtqNbr] != 0; 447 678 } 448 679 449 680 /** 450 * Get name of queue, by idxVirtq, assigned at virtioCoreR3VirtqAttach()681 * Get name of queue, by uVirtqNbr, assigned at virtioCoreR3VirtqAttach() 451 682 * 452 683 * @param pVirtio Pointer to the virtio state. 453 * @param idxVirtqVirtq number.684 * @param uVirtqNbr Virtq number. 454 685 * 455 686 * @returns Pointer to read-only queue name. 456 687 */ 457 DECLINLINE(const char *) virtioCoreVirtqGetName(PVIRTIOCORE pVirtio, uint16_t idxVirtq)458 { 459 Assert((size_t) idxVirtq< RT_ELEMENTS(pVirtio->aVirtqState));460 return pVirtio->aVirtqState[ idxVirtq].szVirtqName;688 DECLINLINE(const char *) virtioCoreVirtqGetName(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 689 { 690 Assert((size_t)uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 691 return pVirtio->aVirtqState[uVirtqNbr].szVirtqName; 461 692 } 462 693 … … 470 701 return pVirtio->uDriverFeatures; 471 702 } 472 473 703 474 704 /** … … 486 716 } 487 717 488 void virtioCoreLogMappedIoValue(const char *pszFunc, const char *pszMember, uint32_t uMemberSize, 718 /** 719 * Log memory-mapped I/O input or output value. 720 * 721 * This is to be invoked by macros that assume they are invoked in functions with 722 * the relevant arguments. (See Virtio_1_0.cpp). 723 * 724 * It is exposed via the API so inheriting device-specific clients can provide similar 725 * logging capabilities for a consistent look-and-feel. 726 * 727 * @param pszFunc To avoid displaying this function's name via __FUNCTION__ or LogFunc() 728 * @param pszMember Name of struct member 729 * @param pv pointer to value 730 * @param cb size of value 731 * @param uOffset offset into member where value starts 732 * @param fWrite True if write I/O 733 * @param fHasIndex True if the member is indexed 734 * @param idx The index if fHasIndex 735 */ 736 const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState);void virtioCoreLogMappedIoValue(const char *pszFunc, const char *pszMember, uint32_t uMemberSize, 489 737 const void *pv, uint32_t cb, uint32_t uOffset, 490 738 int fWrite, int fHasIndex, uint32_t idx); 491 739 492 /* Debug assist functions for consumer device code */ 740 /** 741 * Debug assist for any consumer device code that inherits VIRTIOCORE 742 * 743 * Does a formatted hex dump using Log(()), recommend using VIRTIO_HEX_DUMP() macro to 744 * control enabling of logging efficiently. 745 * 746 * @param pv pointer to buffer to dump contents of 747 * @param cb count of characters to dump from buffer 748 * @param uBase base address of per-row address prefixing of hex output 749 * @param pszTitle Optional title. If present displays title that lists 750 * provided text with value of cb to indicate size next to it. 751 */ 493 752 void virtioCoreHexDump(uint8_t *pv, uint32_t cb, uint32_t uBase, const char *pszTitle); 753 754 /** 755 * Debug assist for any consumer device code that inherits VIRTIOCORE 756 & 757 * Do a hex dump of memory in guest physical context 758 * 759 * @param GCPhys pointer to buffer to dump contents of 760 * @param cb count of characters to dump from buffer 761 * @param uBase base address of per-row address prefixing of hex output 762 * @param pszTitle Optional title. If present displays title that lists 763 * provided text with value of cb to indicate size next to it. 764 */ 494 765 void virtioCoreGCPhysHexDump(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint16_t cb, uint32_t uBase, const char *pszTitle); 495 766 496 767 /** The following virtioCoreSgBuf*() functions mimic the functionality of the related RT s/g functions, 768 * except they work with the data type GCPhys rather than void * 769 */ 497 770 void virtioCoreSgBufInit(PVIRTIOSGBUF pGcSgBuf, PVIRTIOSGSEG paSegs, size_t cSegs); 498 771 void virtioCoreSgBufReset(PVIRTIOSGBUF pGcSgBuf); … … 504 777 size_t virtioCoreSgBufCalcTotalLength(PVIRTIOSGBUF pGcSgBuf); 505 778 779 /** Misc VM and PDM boilerplate */ 506 780 int virtioCoreR3SaveExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM); 507 781 int virtioCoreR3LoadExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM); … … 511 785 const char *pcszInstance, uint64_t fDevSpecificFeatures, void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg); 512 786 int virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio); 787 788 513 789 const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState); 514 790
Note:
See TracChangeset
for help on using the changeset viewer.