- Timestamp:
- Apr 1, 2020 7:18:42 AM (5 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp
r83188 r83499 75 75 76 76 #define QUEUE_NAME(a_pVirtio, a_idxQueue) ((a_pVirtio)->virtqState[(a_idxQueue)].szVirtqName) 77 #define VIRTQNAME(idxQueue) 78 #define CBVIRTQNAME(idxQueue) 77 #define VIRTQNAME(idxQueue) (pThis->aszVirtqNames[idxQueue]) 78 #define CBVIRTQNAME(idxQueue) RTStrNLen(VIRTQNAME(idxQueue), sizeof(VIRTQNAME(idxQueue))) 79 79 #define FEATURE_ENABLED(feature) (!!(pThis->fNegotiatedFeatures & VIRTIONET_F_##feature)) 80 80 #define FEATURE_DISABLED(feature) (!FEATURE_ENABLED(feature)) … … 82 82 83 83 #define SET_LINK_UP(pState) \ 84 LogFunc(("SET_LINK_UP\n")); \ 84 85 pState->virtioNetConfig.uStatus |= VIRTIONET_F_LINK_UP; \ 85 86 virtioCoreNotifyConfigChanged(&pThis->Virtio) 86 87 87 88 #define SET_LINK_DOWN(pState) \ 88 pState->virtioNetConfig.uStatus &= !VIRTIONET_F_LINK_UP; \ 89 LogFunc(("SET_LINK_DOWN\n")); \ 90 pState->virtioNetConfig.uStatus &= ~VIRTIONET_F_LINK_UP; \ 89 91 virtioCoreNotifyConfigChanged(&pThis->Virtio) 90 92 … … 194 196 #pragma pack() 195 197 196 #define VIRTIONET_F_LINK_UP RT_BIT(1)/**< config status: Link is up */197 #define VIRTIONET_F_ANNOUNCE RT_BIT(2)/**< config status: Announce */198 #define VIRTIONET_F_LINK_UP 1 /**< config status: Link is up */ 199 #define VIRTIONET_F_ANNOUNCE 2 /**< config status: Announce */ 198 200 199 201 /** @name VirtIO 1.0 NET Host Device device specific control types … … 1454 1456 1455 1457 uint32_t cbDescChainLeft = pDescChain->cbPhysReturn; 1456 1458 uint8_t cbHdr = sizeof(VIRTIONET_PKT_HDR_T); 1457 1459 /* Fill the Guest Rx buffer with data received from the interface */ 1458 1460 for (uint16_t cSegs = 0; uOffset < cb && cbDescChainLeft; ) … … 1461 1463 { 1462 1464 /* Lead with packet header */ 1463 paVirtSegsToGuest[0].cbSeg = sizeof(VIRTIONET_PKT_HDR_T);1464 paVirtSegsToGuest[0].pvSeg = RTMemAlloc( sizeof(VIRTIONET_PKT_HDR_T));1465 paVirtSegsToGuest[0].cbSeg = cbHdr; 1466 paVirtSegsToGuest[0].pvSeg = RTMemAlloc(cbHdr); 1465 1467 AssertReturn(paVirtSegsToGuest[0].pvSeg, VERR_NO_MEMORY); 1466 cbDescChainLeft -= sizeof(VIRTIONET_PKT_HDR_T);1467 1468 memcpy(paVirtSegsToGuest[0].pvSeg, &rxPktHdr, sizeof(VIRTIONET_PKT_HDR_T));1468 cbDescChainLeft -= cbHdr; 1469 1470 memcpy(paVirtSegsToGuest[0].pvSeg, &rxPktHdr, cbHdr); 1469 1471 1470 1472 /* Calculate & cache the field we will need to update later in gcPhys memory */ … … 1474 1476 cSegs++; 1475 1477 } 1478 1476 1479 if (cSegs >= cSegsAllocated) 1477 1480 { … … 1507 1510 1508 1511 /* Dump Rx Pkt after it's been written to guest physical memory via the virtio core API */ 1509 if (pThis->fLog)1510 {1512 // if (pThis->fLog) 1513 // { 1511 1514 virtioNetDumpGcPhysRxBuf(pDevIns, &rxPktHdr, cDescs, (uint8_t *)pvBuf, cb, 1512 1515 gcPhysPktHdrNumBuffers - RT_UOFFSETOF(VIRTIONET_PKT_HDR_T, uNumBuffers), 1513 1516 cb + sizeof(VIRTIONET_PKT_HDR_T)); 1514 }1517 // } 1515 1518 1516 1519 virtioCoreQueueSync(pDevIns, &pThis->Virtio, RXQIDX_QPAIR(idxQueue)); … … 1518 1521 1519 1522 if (pThis->fLog) { 1520 RTThreadSleep(500);1521 1523 // RTThreadSleep(500); 1524 // RT_BREAKPOINT(); 1522 1525 pThis->fBp = false; 1523 1526 } … … 1911 1914 } 1912 1915 1913 static boolvirtioNetR3ReadHeader(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, PVIRTIONET_PKT_HDR_T pPktHdr, uint32_t cbMax)1916 static int virtioNetR3ReadHeader(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, PVIRTIONET_PKT_HDR_T pPktHdr, uint32_t cbMax) 1914 1917 { 1915 1918 int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pPktHdr, sizeof(*pPktHdr)); 1916 1919 if (RT_FAILURE(rc)) 1917 return false;1918 1919 Log 4(("virtio-net: header flags=%x gso-type=%x len=%x gso-size=%x Chksum-start=%x Chksum-offset=%x cb=%x\n",1920 return rc; 1921 1922 Log(("virtio-net: header flags=%x gso-type=%x len=%x gso-size=%x Chksum-start=%x Chksum-offset=%x cb=%x\n", 1920 1923 pPktHdr->uFlags, pPktHdr->uGsoType, pPktHdr->uHdrLen, 1921 1924 pPktHdr->uGsoSize, pPktHdr->uChksumStart, pPktHdr->uChksumOffset, cbMax)); … … 1926 1929 1927 1930 /* Segmentation offloading cannot be done without checksumming, and we do not support ECN */ 1928 if ( RT_UNLIKELY(!(pPktHdr->uFlags & VIRTIONET_HDR_F_NEEDS_CSUM))1929 | RT_UNLIKELY(pPktHdr->uGsoType & VIRTIONET_HDR_GSO_ECN))1930 return false;1931 AssertMsgReturn( RT_LIKELY(pPktHdr->uFlags & VIRTIONET_HDR_F_NEEDS_CSUM) 1932 && RT_UNLIKELY(pPktHdr->uGsoType & VIRTIONET_HDR_GSO_ECN), 1933 ("Unsupported ECN request in pkt header\n"), VERR_NOT_SUPPORTED); 1931 1934 1932 1935 switch (pPktHdr->uGsoType) … … 1940 1943 break; 1941 1944 default: 1942 return false; 1945 LogFunc(("Bad GSO type in packet header\n")); 1946 return VERR_INVALID_PARAMETER; 1943 1947 } 1944 1948 /* Header + MSS must not exceed the packet size. */ 1945 if (RT_UNLIKELY(uMinHdrSize + pPktHdr->uChksumStart + pPktHdr->uGsoSize > cbMax))1946 return false;1947 } 1948 /* Checksum must fit into the frame (validating both checksum fields). */ 1949 if (( pPktHdr->uFlags & VIRTIONET_HDR_F_NEEDS_CSUM)1950 && sizeof(uint16_t) + pPktHdr->uChksumStart + pPktHdr->uChksumOffset > cbMax)1951 return false;1952 Log4Func(("returning true\n")); 1953 return true;1949 AssertMsgReturn(RT_LIKELY(uMinHdrSize + pPktHdr->uChksumStart + pPktHdr->uGsoSize <= cbMax), 1950 ("Header plus message exceeds packet size"), VERR_BUFFER_OVERFLOW); 1951 } 1952 1953 AssertMsgReturn( !pPktHdr->uFlags & VIRTIONET_HDR_F_NEEDS_CSUM 1954 || sizeof(uint16_t) + pPktHdr->uChksumStart + pPktHdr->uChksumOffset <= cbMax, 1955 ("Checksum doesn't fit into pkt header\n"), VERR_BUFFER_OVERFLOW); 1956 1957 return VINF_SUCCESS; 1954 1958 } 1955 1959 … … 1957 1961 PPDMNETWORKGSO pGso, PVIRTIONET_PKT_HDR_T pPktHdr) 1958 1962 { 1959 LogFunc(("\n"));1960 1963 virtioNetR3PacketDump(pThis, (uint8_t *)pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, "--> Outgoing"); 1961 1964 if (pGso) … … 2009 2012 { 2010 2013 2011 LogFunc(("\n"));2012 2014 PVIRTIOCORE pVirtio = &pThis->Virtio; 2013 2015 … … 2045 2047 } 2046 2048 2047 unsigned int cbPktHdr = sizeof(VIRTIONET_PKT_HDR_T);2048 2049 2049 int cPkts = virtioCoreR3QueuePendingCount(pVirtio->pDevIns, pVirtio, idxQueue); 2050 2050 if (!cPkts) … … 2064 2064 int rc; 2065 2065 PVIRTIO_DESC_CHAIN_T pDescChain; 2066 while ((rc = virtioCoreR3QueuePeek(pVirtio->pDevIns, pVirtio, idxQueue, &pDescChain)) )2066 while ((rc = virtioCoreR3QueuePeek(pVirtio->pDevIns, pVirtio, idxQueue, &pDescChain)) == VINF_SUCCESS) 2067 2067 { 2068 2068 if (RT_SUCCESS(rc)) … … 2074 2074 } 2075 2075 2076 uint32_t cSegsFromGuest = pDescChain->pSgPhysSend->cSegs; 2077 PVIRTIOSGSEG paSegsFromGuest = pDescChain->pSgPhysSend->paSegs; 2078 2079 if (cSegsFromGuest < 2 || paSegsFromGuest[0].cbSeg != cbPktHdr) 2080 { 2081 /* This check could be made more complex, because in theory (but not likely nor 2082 * seen in practice) the first segment could contain header and data. */ 2083 LogFunc(("%s The first segment is not the header! (%u < 2 || %u != %u).\n", 2084 INSTANCE(pThis), cSegsFromGuest, paSegsFromGuest[0].cbSeg, cbPktHdr)); 2085 break; 2086 } 2076 PVIRTIOSGBUF pSgPhysSend = pDescChain->pSgPhysSend; 2077 PVIRTIOSGSEG paSegsFromGuest = pSgPhysSend->paSegs; 2078 uint32_t cSegsFromGuest = pSgPhysSend->cSegs; 2087 2079 2088 2080 VIRTIONET_PKT_HDR_T PktHdr; 2089 2081 uint32_t uSize = 0; 2090 2082 2083 Assert(paSegsFromGuest[0].cbSeg >= sizeof(PktHdr)); 2084 2091 2085 /* Compute total frame size. */ 2092 for (unsigned i = 1; i < cSegsFromGuest && uSize < VIRTIONET_MAX_FRAME_SIZE; i++)2086 for (unsigned i = 0; i < cSegsFromGuest && uSize < VIRTIONET_MAX_FRAME_SIZE; i++) 2093 2087 uSize += paSegsFromGuest[i].cbSeg; 2094 2088 … … 2100 2094 uSize = VIRTIONET_MAX_FRAME_SIZE; 2101 2095 2102 if (pThisCC->pDrv && virtioNetR3ReadHeader(pDevIns, paSegsFromGuest[0].gcPhys, &PktHdr, uSize))2096 if (pThisCC->pDrv) 2103 2097 { 2104 2098 PDMNETWORKGSO Gso, *pGso = virtioNetR3SetupGsoCtx(&Gso, &PktHdr); … … 2109 2103 if (RT_SUCCESS(rc)) 2110 2104 { 2111 pSgBufToPdmLeafDevice->cbUsed = uSize; 2112 2113 /* Assemble a complete frame. */ 2114 for (unsigned i = 1; i < cSegsFromGuest && uSize > 0; i++) 2105 uSize -= sizeof(PktHdr); 2106 rc = virtioNetR3ReadHeader(pDevIns, paSegsFromGuest[0].gcPhys, &PktHdr, sizeof(PktHdr)); 2107 virtioCoreSgBufAdvance(pSgPhysSend, sizeof(PktHdr)); 2108 2109 uint64_t uOffset = 0; 2110 size_t cbCopied = 0; 2111 size_t cbTotal = 0; 2112 size_t cbRemain = pSgBufToPdmLeafDevice->cbUsed = uSize; 2113 while (cbRemain) 2115 2114 { 2116 unsigned uOffset; 2117 unsigned cbSeg = RT_MIN(uSize, paSegsFromGuest[i].cbSeg); 2118 2119 PDMDevHlpPCIPhysRead(pDevIns, paSegsFromGuest[i].gcPhys, 2120 ((uint8_t *)pSgBufToPdmLeafDevice->aSegs[0].pvSeg) + uOffset, 2121 cbSeg); 2122 uOffset += cbSeg; 2123 uSize -= cbSeg; 2115 PVIRTIOSGSEG paSeg = &pSgPhysSend->paSegs[pSgPhysSend->idxSeg]; 2116 uint64_t srcSgStart = (uint64_t)paSeg->gcPhys; 2117 uint64_t srcSgLen = (uint64_t)paSeg->cbSeg; 2118 uint64_t srcSgCur = (uint64_t)pSgPhysSend->gcPhysCur; 2119 cbCopied = RT_MIN((uint64_t)cbRemain, srcSgLen - (srcSgCur - srcSgStart)); 2120 PDMDevHlpPCIPhysRead(pDevIns, 2121 (RTGCPHYS)pSgPhysSend->gcPhysCur, 2122 ((uint8_t *)pSgBufToPdmLeafDevice->aSegs[0].pvSeg) + uOffset, cbCopied); 2123 virtioCoreSgBufAdvance(pSgPhysSend, cbCopied); 2124 cbRemain -= cbCopied; 2125 uOffset += cbCopied; 2126 cbTotal += cbCopied; 2124 2127 } 2128 2129 LogFunc((".... Copied %lu bytes to %lu byte guest buffer, residual=%lu\n", 2130 cbTotal, pDescChain->cbPhysSend, pDescChain->cbPhysSend - cbTotal)); 2131 2125 2132 rc = virtioNetR3TransmitFrame(pThis, pThisCC, pSgBufToPdmLeafDevice, pGso, &PktHdr); 2126 2133 if (RT_FAILURE(rc)) … … 2136 2143 break; 2137 2144 } 2145 2146 /* Remove this descriptor chain from the available ring */ 2147 virtioCoreR3QueueSkip(pVirtio, idxQueue); 2148 2149 /* No data to return to guest, but call is needed put elem (e.g. desc chain) on used ring */ 2150 virtioCoreR3QueuePut(pVirtio->pDevIns, pVirtio, idxQueue, NULL, pDescChain, false); 2151 2152 virtioCoreQueueSync(pVirtio->pDevIns, pVirtio, idxQueue); 2138 2153 } 2139 /* Remove this descriptor chain from the available ring */2140 virtioCoreR3QueueSkip(pVirtio, idxQueue);2141 2142 /* No data to return to guest, but call is needed put elem (e.g. desc chain) on used ring */2143 virtioCoreR3QueuePut(pVirtio->pDevIns, pVirtio, idxQueue, NULL, pDescChain, false);2144 2145 virtioCoreQueueSync(pVirtio->pDevIns, pVirtio, idxQueue);2146 2147 2154 } 2148 2155 virtioNetR3SetWriteLed(pThisCC, false); … … 2270 2277 else if (IS_TX_QUEUE(idxQueue)) 2271 2278 { 2272 LogFunc(("Worker thread notified of pending Xmit packets!!!!!!\n"));2273 2279 Log10Func(("%s Notified of data to transmit\n", INSTANCE(pThis))); 2274 2280 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, … … 2481 2487 LogFunc(("%s VirtIO ready\n-----------------------------------------------------------------------------------------\n", 2482 2488 INSTANCE(pThis))); 2489 pThis->virtioNetConfig.uStatus = pThis->fCableConnected ? VIRTIONET_F_LINK_UP : 0; 2483 2490 2484 2491 pThis->fResetting = false; -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r83187 r83499 766 766 uint16_t uAvailRingIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue); 767 767 uint16_t uNextAvailIdx = pVirtio->virtqState[idxQueue].uAvailIdx; 768 int16_t iDelta = uAvailRingIdx - uNextAvailIdx;769 768 uint16_t uDelta = uAvailRingIdx - uNextAvailIdx; 770 return iDelta >= 0 ? uDelta : VIRTQ_MAX_CNT + uDelta; 769 if (uAvailRingIdx > uNextAvailIdx) 770 return uDelta; 771 return VIRTQ_MAX_CNT + uDelta; 771 772 } 772 773 /** … … 906 907 VIRTQNAME(pVirtio, idxQueue), virtioReadUsedRingIdx(pDevIns, pVirtio, idxQueue))); 907 908 908 /* 909 * Copy s/g buf (virtual memory) to guest phys mem (IN direction). This virtual memory 910 * block will be small (fixed portion of response header + sense buffer area or 911 * control commands or error return values)... The bulk of req data xfers to phys mem 912 * is handled by client */ 909 /* Copy s/g buf (virtual memory) to guest phys mem (IN direction). */ 913 910 914 911 size_t cbCopy = 0, cbTotal = 0, cbRemain = 0; … … 937 934 } 938 935 939 940 936 /* If this write-ahead crosses threshold where the driver wants to get an event flag it */ 941 937 if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX) … … 946 942 * Place used buffer's descriptor in used ring but don't update used ring's slot index. 947 943 * That will be done with a subsequent client call to virtioCoreQueueSync() */ 948 virtioWriteUsedElem(pDevIns, pVirtio, idxQueue, pVirtq->uUsedIdx++, pDescChain->uHeadIdx, (uint32_t)cbCopy); 949 950 Log6Func((".... Copied %zu bytes in %d segs to %u byte buffer, residual=%zu\n", 951 cbTotal - cbRemain, pSgVirtReturn->cSegs, pDescChain->cbPhysReturn, pDescChain->cbPhysReturn - cbCopy)); 944 virtioWriteUsedElem(pDevIns, pVirtio, idxQueue, pVirtq->uUsedIdx++, pDescChain->uHeadIdx, (uint32_t)cbTotal); 945 946 if (pSgVirtReturn) 947 Log6Func((".... Copied %zu bytes in %d segs to %u byte buffer, residual=%zu\n", 948 cbTotal - cbRemain, pSgVirtReturn->cSegs, pDescChain->cbPhysReturn, pDescChain->cbPhysReturn - cbTotal)); 952 949 953 950 Log6Func(("Write ahead used_idx=%u, %s used_idx=%u\n", … … 1069 1066 return; 1070 1067 } 1071 /* REMOVE THIS!!!!!!! DON'T INTEGRATE! EXPERIMENTAL/DEBUG */ 1072 //virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[idxQueue], fForce); 1073 // Log6Func(("...skipping interrupt. Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n")); 1068 1069 Log6Func(("...skipping interrupt. Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n")); 1074 1070 } 1075 1071 }
Note:
See TracChangeset
for help on using the changeset viewer.