Changeset 84803 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Jun 12, 2020 6:17:35 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 138609
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp
r84775 r84803 61 61 #define VIRTIONET_SAVED_STATE_VERSION UINT32_C(1) 62 62 #define VIRTIONET_MAX_QPAIRS 1 63 #define VIRTIONET_MAX_ QUEUES (VIRTIONET_MAX_QPAIRS * 2 + 1)63 #define VIRTIONET_MAX_VIRTQS (VIRTIONET_MAX_QPAIRS * 2 + 1) 64 64 #define VIRTIONET_MAX_FRAME_SIZE 65535 + 18 /**< Max IP pkt size + Ethernet header with VLAN tag */ 65 65 #define VIRTIONET_MAC_FILTER_LEN 32 … … 67 67 #define VIRTIONET_PREALLOCATE_RX_SEG_COUNT 32 68 68 69 #define VIRTQNAME(idx Queue) (pThis->aQueues[idxQueue]->szName)70 #define CBVIRTQNAME(idx Queue) RTStrNLen(VIRTQNAME(idxQueue), sizeof(VIRTQNAME(idxQueue)))69 #define VIRTQNAME(idxVirtq) (pThis->aVirtqs[idxVirtq]->szName) 70 #define CBVIRTQNAME(idxVirtq) RTStrNLen(VIRTQNAME(idxVirtq), sizeof(VIRTQNAME(idxVirtq))) 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, idx Queue) \76 (virtioCore QueueAvailCount(pDevIns, pVirtio, idxQueue) == 0)75 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, idxVirtq) \ 76 (virtioCoreVirtqAvailCount(pDevIns, pVirtio, idxVirtq) == 0) 77 77 78 78 #define SET_LINK_UP(pState) \ … … 90 90 91 91 /* Macros to calculate queue specific index number VirtIO 1.0, 5.1.2 */ 92 #define IS_TX_ QUEUE(n) ((n) != CTRLQIDX && ((n) & 1))93 #define IS_RX_ QUEUE(n) ((n) != CTRLQIDX && !IS_TX_QUEUE(n))94 #define IS_CTRL_ QUEUE(n) ((n) == CTRLQIDX)92 #define IS_TX_VIRTQ(n) ((n) != CTRLQIDX && ((n) & 1)) 93 #define IS_RX_VIRTQ(n) ((n) != CTRLQIDX && !IS_TX_VIRTQ(n)) 94 #define IS_CTRL_VIRTQ(n) ((n) == CTRLQIDX) 95 95 #define RXQIDX(qPairIdx) (qPairIdx * 2) 96 96 #define TXQIDX(qPairIdx) (qPairIdx * 2 + 1) … … 306 306 struct VIRTIONETWORKERR3; 307 307 308 typedef struct VIRTIONET QUEUE308 typedef struct VIRTIONETVIRTQ 309 309 { 310 310 struct VIRTIONETWORKER *pWorker; /**< Pointer to R0 worker struct */ … … 312 312 uint16_t idx; /**< Index of this queue */ 313 313 uint16_t align; 314 char szName[VIRTIO_MAX_ QUEUE_NAME_SIZE]; /**< Queuename */315 bool fCtl Queue; /**< If set this queue is the control queue */314 char szName[VIRTIO_MAX_VIRTQ_NAME_SIZE]; /**< Virtq name */ 315 bool fCtlVirtq; /**< If set this queue is the control queue */ 316 316 bool fHasWorker; /**< If set this queue has an associated worker */ 317 317 bool fAttachedToVirtioCore; /**< Set if queue attached to virtio core */ 318 318 uint8_t pad; 319 } VIRTIONET QUEUE, *PVIRTIONETQUEUE;319 } VIRTIONETVIRTQ, *PVIRTIONETVIRTQ; 320 320 321 321 /** … … 325 325 { 326 326 SUPSEMEVENT hEvtProcess; /**< handle of associated sleep/wake-up semaphore */ 327 PVIRTIONET QUEUE pQueue; /**< pointer to queue */327 PVIRTIONETVIRTQ pVirtq; /**< pointer to queue */ 328 328 uint16_t idx; /**< Index of this worker */ 329 329 bool volatile fSleeping; /**< Flags whether worker thread is sleeping or not */ … … 341 341 { 342 342 R3PTRTYPE(PPDMTHREAD) pThread; /**< pointer to worker thread's handle */ 343 PVIRTIONET QUEUE pQueue; /**< pointer to queue */343 PVIRTIONETVIRTQ pVirtq; /**< pointer to queue */ 344 344 uint16_t idx; /**< Index of this worker */ 345 345 uint16_t pad; … … 362 362 363 363 /** Per device-bound virtq worker-thread contexts (eventq slot unused) */ 364 VIRTIONETWORKER aWorkers[VIRTIONET_MAX_ QUEUES];364 VIRTIONETWORKER aWorkers[VIRTIONET_MAX_VIRTQS]; 365 365 366 366 /** Track which VirtIO queues we've attached to */ 367 VIRTIONET QUEUE aQueues[VIRTIONET_MAX_QUEUES];367 VIRTIONETVIRTQ aVirtqs[VIRTIONET_MAX_VIRTQS]; 368 368 369 369 /** PDM device Instance name */ … … 377 377 378 378 /** Number of virtqueues total (which includes each queue of each pair plus one control queue */ 379 uint16_t cVirt Queues;379 uint16_t cVirtVirtqs; 380 380 381 381 /** Number of worker threads (one for the control queue and one for each Tx queue) */ … … 485 485 486 486 /** Per device-bound virtq worker-thread contexts (eventq slot unused) */ 487 VIRTIONETWORKERR3 aWorkers[VIRTIONET_MAX_ QUEUES];487 VIRTIONETWORKERR3 aWorkers[VIRTIONET_MAX_VIRTQS]; 488 488 489 489 /** The device instance. … … 613 613 614 614 /** 615 * @callback_method_impl{VIRTIOCORER0,pfn QueueNotified}616 */ 617 static DECLCALLBACK(void) virtioNet QueueNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue)615 * @callback_method_impl{VIRTIOCORER0,pfnVirtqNotified} 616 */ 617 static DECLCALLBACK(void) virtioNetVirtqNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxVirtq) 618 618 { 619 619 RT_NOREF(pVirtio); 620 620 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 621 621 622 PVIRTIONET QUEUE pQueue = &pThis->aQueues[idxQueue];623 PVIRTIONETWORKER pWorker = p Queue->pWorker;622 PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[idxVirtq]; 623 PVIRTIONETWORKER pWorker = pVirtq->pWorker; 624 624 625 625 #if defined (IN_RING3) && defined (LOG_ENABLED) … … 627 627 #endif 628 628 629 if (IS_RX_ QUEUE(idxQueue))630 { 631 uint16_t cBufsAvailable = virtioCore QueueAvailCount(pDevIns, pVirtio, idxQueue);629 if (IS_RX_VIRTQ(idxVirtq)) 630 { 631 uint16_t cBufsAvailable = virtioCoreVirtqAvailCount(pDevIns, pVirtio, idxVirtq); 632 632 633 633 if (cBufsAvailable) 634 634 { 635 635 Log10Func(("%s %u empty bufs added to %s by guest (notifying leaf device)\n", 636 pThis->szInst, cBufsAvailable, p Queue->szName));636 pThis->szInst, cBufsAvailable, pVirtq->szName)); 637 637 virtioNetWakeupRxBufWaiter(pDevIns); 638 638 } 639 639 else 640 640 LogRel(("%s \n\n***WARNING: %s notified but no empty bufs added by guest! (skip notifying of leaf device)\n\n", 641 pThis->szInst, p Queue->szName));642 } 643 else if (IS_TX_ QUEUE(idxQueue) || IS_CTRL_QUEUE(idxQueue))641 pThis->szInst, pVirtq->szName)); 642 } 643 else if (IS_TX_VIRTQ(idxVirtq) || IS_CTRL_VIRTQ(idxVirtq)) 644 644 { 645 645 /* Wake queue's worker thread up if sleeping (e.g. a Tx queue, or the control queue */ … … 648 648 if (ASMAtomicReadBool(&pWorker->fSleeping)) 649 649 { 650 Log10Func(("%s %s has available buffers - waking worker.\n", pThis->szInst, p Queue->szName));650 Log10Func(("%s %s has available buffers - waking worker.\n", pThis->szInst, pVirtq->szName)); 651 651 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess); 652 652 AssertRC(rc); … … 654 654 else 655 655 { 656 Log10Func(("%s %s has available buffers - worker already awake\n", pThis->szInst, p Queue->szName));656 Log10Func(("%s %s has available buffers - worker already awake\n", pThis->szInst, pVirtq->szName)); 657 657 } 658 658 } 659 659 else 660 660 { 661 Log10Func(("%s %s has available buffers - waking worker.\n", pThis->szInst, p Queue->szName));661 Log10Func(("%s %s has available buffers - waking worker.\n", pThis->szInst, pVirtq->szName)); 662 662 } 663 663 } 664 664 else 665 LogRelFunc(("%s unrecognized queue %s (idx=%d) notified\n", p Queue->szName, idxQueue));665 LogRelFunc(("%s unrecognized queue %s (idx=%d) notified\n", pVirtq->szName, idxVirtq)); 666 666 } 667 667 … … 677 677 678 678 Log10Func(("%s\n", pThis->szInst)); 679 RT_NOREF(pThis); 679 680 680 681 return PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess); … … 684 685 DECLINLINE(void) virtioNetR3SetVirtqNames(PVIRTIONET pThis) 685 686 { 686 RTStrCopy(pThis->a Queues[CTRLQIDX].szName, VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq");687 RTStrCopy(pThis->aVirtqs[CTRLQIDX].szName, VIRTIO_MAX_VIRTQ_NAME_SIZE, "controlq"); 687 688 for (uint16_t qPairIdx = 0; qPairIdx < pThis->cVirtqPairs; qPairIdx++) 688 689 { 689 RTStrPrintf(pThis->a Queues[RXQIDX(qPairIdx)].szName, VIRTIO_MAX_QUEUE_NAME_SIZE, "receiveq<%d>", qPairIdx);690 RTStrPrintf(pThis->a Queues[TXQIDX(qPairIdx)].szName, VIRTIO_MAX_QUEUE_NAME_SIZE, "transmitq<%d>", qPairIdx);690 RTStrPrintf(pThis->aVirtqs[RXQIDX(qPairIdx)].szName, VIRTIO_MAX_VIRTQ_NAME_SIZE, "receiveq<%d>", qPairIdx); 691 RTStrPrintf(pThis->aVirtqs[TXQIDX(qPairIdx)].szName, VIRTIO_MAX_VIRTQ_NAME_SIZE, "transmitq<%d>", qPairIdx); 691 692 } 692 693 } … … 813 814 bool fState = pszArgs && (*pszArgs == 's' || *pszArgs == 'S'); /* "state" */ 814 815 bool fPointers = pszArgs && (*pszArgs == 'p' || *pszArgs == 'P'); /* "pointers" */ 815 bool f Queues = pszArgs && (*pszArgs == 'q' || *pszArgs == 'Q'); /* "queues */816 bool fVirtqs = pszArgs && (*pszArgs == 'q' || *pszArgs == 'Q'); /* "queues */ 816 817 817 818 /* Show basic information. */ … … 836 837 837 838 /* Show queues (and associate worker info if applicable) */ 838 if (fAll || f Queues)839 { 840 pHlp->pfnPrintf(pHlp, " Queueinformation:\n\n");841 842 for (int idx Queue = 0; idxQueue < pThis->cVirtQueues; idxQueue++)839 if (fAll || fVirtqs) 840 { 841 pHlp->pfnPrintf(pHlp, "Virtq information:\n\n"); 842 843 for (int idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++) 843 844 { 844 PVIRTIONET QUEUE pQueue = &pThis->aQueues[idxQueue];845 846 if (p Queue->fHasWorker)845 PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[idxVirtq]; 846 847 if (pVirtq->fHasWorker) 847 848 { 848 PVIRTIONETWORKER pWorker = p Queue->pWorker;849 PVIRTIONETWORKERR3 pWorkerR3 = p Queue->pWorkerR3;849 PVIRTIONETWORKER pWorker = pVirtq->pWorker; 850 PVIRTIONETWORKERR3 pWorkerR3 = pVirtq->pWorkerR3; 850 851 851 852 if (pWorker->fAssigned) 852 853 { 853 854 pHlp->pfnPrintf(pHlp, " %-15s (pThread: %p %s) ", 854 p Queue->szName,855 pVirtq->szName, 855 856 pWorkerR3->pThread, 856 857 virtioNetThreadStateName(pWorkerR3->pThread)); 857 if (p Queue->fAttachedToVirtioCore)858 if (pVirtq->fAttachedToVirtioCore) 858 859 { 859 860 pHlp->pfnPrintf(pHlp, "worker: "); … … 868 869 else 869 870 { 870 pHlp->pfnPrintf(pHlp, " %-15s (INetworkDown's thread) %s", p Queue->szName,871 p Queue->fAttachedToVirtioCore ? "" : "not attached to virtio core");871 pHlp->pfnPrintf(pHlp, " %-15s (INetworkDown's thread) %s", pVirtq->szName, 872 pVirtq->fAttachedToVirtioCore ? "" : "not attached to virtio core"); 872 873 } 873 874 pHlp->pfnPrintf(pHlp, "\n"); 874 virtioCoreR3 QueueInfo(pDevIns, pHlp, pszArgs, idxQueue);875 virtioCoreR3VirtqInfo(pDevIns, pHlp, pszArgs, idxVirtq); 875 876 pHlp->pfnPrintf(pHlp, " ---------------------------------------------------------------------\n"); 876 877 pHlp->pfnPrintf(pHlp, "\n"); … … 900 901 pHlp->pfnPrintf(pHlp, " uDeviceStatus ............. 0x%x\n", pThis->Virtio.uDeviceStatus); 901 902 pHlp->pfnPrintf(pHlp, " cVirtqPairs .,............. %d\n", pThis->cVirtqPairs); 902 pHlp->pfnPrintf(pHlp, " cVirt Queues .,............. %d\n", pThis->cVirtQueues);903 pHlp->pfnPrintf(pHlp, " cVirtVirtqs .,............. %d\n", pThis->cVirtVirtqs); 903 904 pHlp->pfnPrintf(pHlp, " cWorkers .................. %d\n", pThis->cWorkers); 904 905 pHlp->pfnPrintf(pHlp, " MMIO mapping name ......... %d\n", pThisCC->Virtio.pcszMmioName); … … 1135 1136 pHlp->pfnSSMGetU64( pSSM, &pThis->fNegotiatedFeatures); 1136 1137 1137 pHlp->pfnSSMGetU16( pSSM, &pThis->cVirt Queues);1138 pHlp->pfnSSMGetU16( pSSM, &pThis->cVirtVirtqs); 1138 1139 pHlp->pfnSSMGetU16( pSSM, &pThis->cWorkers); 1139 1140 1140 for (int idx Queue = 0; idxQueue < pThis->cVirtQueues; idxQueue++)1141 pHlp->pfnSSMGetBool(pSSM, &pThis->a Queues[idxQueue].fAttachedToVirtioCore);1141 for (int idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++) 1142 pHlp->pfnSSMGetBool(pSSM, &pThis->aVirtqs[idxVirtq].fAttachedToVirtioCore); 1142 1143 1143 1144 int rc; … … 1199 1200 { 1200 1201 PVIRTIONETWORKER pWorker = &pThis->aWorkers[idxWorker]; 1201 PVIRTIONET QUEUE pQueue = pWorker->pQueue;1202 if (p Queue->fAttachedToVirtioCore)1202 PVIRTIONETVIRTQ pVirtq = pWorker->pVirtq; 1203 if (pVirtq->fAttachedToVirtioCore) 1203 1204 { 1204 Log7Func(("%s Waking %s worker.\n", pThis->szInst, p Queue->szName));1205 Log7Func(("%s Waking %s worker.\n", pThis->szInst, pVirtq->szName)); 1205 1206 rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess); 1206 1207 AssertRCReturn(rc, rc); … … 1224 1225 pHlp->pfnSSMPutU64( pSSM, pThis->fNegotiatedFeatures); 1225 1226 1226 pHlp->pfnSSMPutU16( pSSM, pThis->cVirt Queues);1227 pHlp->pfnSSMPutU16( pSSM, pThis->cVirtVirtqs); 1227 1228 pHlp->pfnSSMPutU16( pSSM, pThis->cWorkers); 1228 1229 1229 for (int idx Queue = 0; idxQueue < pThis->cVirtQueues; idxQueue++)1230 pHlp->pfnSSMPutBool(pSSM, pThis->a Queues[idxQueue].fAttachedToVirtioCore);1230 for (int idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++) 1231 pHlp->pfnSSMPutBool(pSSM, pThis->aVirtqs[idxVirtq].fAttachedToVirtioCore); 1231 1232 1232 1233 /* Save config area */ … … 1470 1471 * @thread RX 1471 1472 */ 1472 static int virtioNetR3CheckRxBufsAvail(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONET QUEUE pRxQueue)1473 static int virtioNetR3CheckRxBufsAvail(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETVIRTQ pRxVirtq) 1473 1474 { 1474 1475 int rc = VERR_INVALID_STATE; … … 1477 1478 Log8Func(("%s No Rx bufs available. (VirtIO core not ready)\n", pThis->szInst)); 1478 1479 1479 else if (!virtioCoreIs QueueEnabled(&pThis->Virtio, pRxQueue->idx))1480 Log8Func(("%s No Rx bufs available. (%s not enabled)\n", pThis->szInst, pRx Queue->szName));1481 1482 else if (IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, pRx Queue->idx))1483 Log8Func(("%s No Rx bufs available. (%s empty)\n", pThis->szInst, pRx Queue->szName));1480 else if (!virtioCoreIsVirtqEnabled(&pThis->Virtio, pRxVirtq->idx)) 1481 Log8Func(("%s No Rx bufs available. (%s not enabled)\n", pThis->szInst, pRxVirtq->szName)); 1482 1483 else if (IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, pRxVirtq->idx)) 1484 Log8Func(("%s No Rx bufs available. (%s empty)\n", pThis->szInst, pRxVirtq->szName)); 1484 1485 1485 1486 else 1486 1487 { 1487 Log8Func(("%s Empty guest buffers available in %s\n", pThis->szInst,pRx Queue->szName));1488 Log8Func(("%s Empty guest buffers available in %s\n", pThis->szInst,pRxVirtq->szName)); 1488 1489 rc = VINF_SUCCESS; 1489 1490 } 1490 virtioCore QueueNotifyEnable(&pThis->Virtio, pRxQueue->idx, rc == VERR_INVALID_STATE /* fEnable */);1491 virtioCoreVirtqNotifyEnable(&pThis->Virtio, pRxVirtq->idx, rc == VERR_INVALID_STATE /* fEnable */); 1491 1492 return rc; 1492 1493 } 1493 1494 1494 static bool virtioNetR3RxBufsAvail(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONET QUEUE *pRxQueue)1495 { 1496 for (int idx QueuePair = 0; idxQueuePair < pThis->cVirtqPairs; idxQueuePair++)1497 { 1498 PVIRTIONET QUEUE pThisRxQueue = &pThis->aQueues[RXQIDX(idxQueuePair)];1499 if (RT_SUCCESS(virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pThisRx Queue)))1495 static bool virtioNetR3RxBufsAvail(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETVIRTQ *pRxVirtq) 1496 { 1497 for (int idxVirtqPair = 0; idxVirtqPair < pThis->cVirtqPairs; idxVirtqPair++) 1498 { 1499 PVIRTIONETVIRTQ pThisRxVirtq = &pThis->aVirtqs[RXQIDX(idxVirtqPair)]; 1500 if (RT_SUCCESS(virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pThisRxVirtq))) 1500 1501 { 1501 if (pRx Queue)1502 *pRx Queue = pThisRxQueue;1502 if (pRxVirtq) 1503 *pRxVirtq = pThisRxVirtq; 1503 1504 return true; 1504 1505 } … … 1516 1517 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 1517 1518 1518 if (virtioNetR3RxBufsAvail(pDevIns, pThis, NULL /* pRx Queue*/))1519 if (virtioNetR3RxBufsAvail(pDevIns, pThis, NULL /* pRxVirtq */)) 1519 1520 { 1520 1521 Log10Func(("%s Rx bufs now available, releasing waiter...\n", pThis->szInst)); … … 1530 1531 1531 1532 do { 1532 if (virtioNetR3RxBufsAvail(pDevIns, pThis, NULL /* pRx Queue*/))1533 if (virtioNetR3RxBufsAvail(pDevIns, pThis, NULL /* pRxVirtq */)) 1533 1534 { 1534 1535 Log10Func(("%s Rx bufs now available, releasing waiter...\n", pThis->szInst)); … … 1730 1731 VIRTIONET_PKT_HDR_T *rxPktHdr, uint16_t cSegsAllocated, 1731 1732 PRTSGBUF pVirtSegBufToGuest, PRTSGSEG paVirtSegsToGuest, 1732 PVIRTIONET QUEUE pRxQueue)1733 PVIRTIONETVIRTQ pRxVirtq) 1733 1734 { 1734 1735 uint8_t fAddPktHdr = true; … … 1740 1741 PVIRTIO_DESC_CHAIN_T pDescChain = NULL; 1741 1742 1742 int rc = virtioCoreR3 QueueGet(pDevIns, &pThis->Virtio, pRxQueue->idx, &pDescChain, true);1743 int rc = virtioCoreR3VirtqGet(pDevIns, &pThis->Virtio, pRxVirtq->idx, &pDescChain, true); 1743 1744 AssertMsgReturn(rc == VINF_SUCCESS || rc == VERR_NOT_AVAILABLE, ("%Rrc\n", rc), rc); 1744 1745 … … 1801 1802 Log7Func(("Send Rx pkt to guest...\n")); 1802 1803 STAM_PROFILE_START(&pThis->StatReceiveStore, a); 1803 virtioCoreR3 QueuePut(pDevIns, &pThis->Virtio, pRxQueue->idx,1804 virtioCoreR3VirtqPut(pDevIns, &pThis->Virtio, pRxVirtq->idx, 1804 1805 pVirtSegBufToGuest, pDescChain, true /* fFence */); 1805 1806 STAM_PROFILE_STOP(&pThis->StatReceiveStore, a); … … 1825 1826 rc); 1826 1827 1827 virtioCore QueueSync(pDevIns, &pThis->Virtio, pRxQueue->idx);1828 virtioCoreVirtqSync(pDevIns, &pThis->Virtio, pRxVirtq->idx); 1828 1829 1829 1830 return VINF_SUCCESS; … … 1843 1844 * @param cb Number of bytes available in the buffer. 1844 1845 * @param pGso Pointer to Global Segmentation Offload structure 1845 * @param idxRx QueueRx queue to work with1846 * @param idxRxVirtq Rx queue to work with 1846 1847 * @thread RX 1847 1848 */ 1848 1849 static int virtioNetR3HandleRxPacket(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 1849 const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso, PVIRTIONET QUEUE pRxQueue)1850 const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso, PVIRTIONETVIRTQ pRxVirtq) 1850 1851 { 1851 1852 RT_NOREF(pThisCC); … … 1898 1899 1899 1900 int rc = virtioNetR3CopyRxPktToGuest(pDevIns, pThis, pvBuf, cb, &rxPktHdr, cSegsAllocated, 1900 pVirtSegBufToGuest, paVirtSegsToGuest, pRx Queue);1901 pVirtSegBufToGuest, paVirtSegsToGuest, pRxVirtq); 1901 1902 1902 1903 RTMemFree(paVirtSegsToGuest); … … 1960 1961 selection algorithm feasible or even necessary to prevent starvation? */ 1961 1962 1962 for (int idx QueuePair = 0; idxQueuePair < pThis->cVirtqPairs; idxQueuePair++)1963 { 1964 1965 PVIRTIONET QUEUE pRxQueue = &pThis->aQueues[RXQIDX(idxQueuePair)];1966 if (RT_SUCCESS(!virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pRx Queue)))1963 for (int idxVirtqPair = 0; idxVirtqPair < pThis->cVirtqPairs; idxVirtqPair++) 1964 { 1965 1966 PVIRTIONETVIRTQ pRxVirtq = &pThis->aVirtqs[RXQIDX(idxVirtqPair)]; 1967 if (RT_SUCCESS(!virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pRxVirtq))) 1967 1968 { 1968 1969 /* Drop packets if VM is not running or cable is disconnected. */ … … 1976 1977 if (virtioNetR3AddressFilter(pThis, pvBuf, cb)) 1977 1978 { 1978 rc = virtioNetR3HandleRxPacket(pDevIns, pThis, pThisCC, pvBuf, cb, pGso, pRx Queue);1979 rc = virtioNetR3HandleRxPacket(pDevIns, pThis, pThisCC, pvBuf, cb, pGso, pRxVirtq); 1979 1980 STAM_REL_COUNTER_ADD(&pThis->StatReceiveBytes, cb); 1980 1981 } … … 2282 2283 RTSgBufInit(pReturnSegBuf, paReturnSegs, cSegs); 2283 2284 2284 virtioCoreR3 QueuePut(pDevIns, &pThis->Virtio, CTRLQIDX, pReturnSegBuf, pDescChain, true /* fFence */);2285 virtioCore QueueSync(pDevIns, &pThis->Virtio, CTRLQIDX);2285 virtioCoreR3VirtqPut(pDevIns, &pThis->Virtio, CTRLQIDX, pReturnSegBuf, pDescChain, true /* fFence */); 2286 virtioCoreVirtqSync(pDevIns, &pThis->Virtio, CTRLQIDX); 2286 2287 2287 2288 for (int i = 0; i < cSegs; i++) … … 2394 2395 2395 2396 static void virtioNetR3TransmitPendingPackets(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 2396 PVIRTIONET QUEUE pTxQueue, bool fOnWorkerThread)2397 PVIRTIONETVIRTQ pTxVirtq, bool fOnWorkerThread) 2397 2398 { 2398 2399 … … 2432 2433 } 2433 2434 2434 int cPkts = virtioCore QueueAvailCount(pVirtio->pDevInsR3, pVirtio, pTxQueue->idx);2435 int cPkts = virtioCoreVirtqAvailCount(pVirtio->pDevInsR3, pVirtio, pTxVirtq->idx); 2435 2436 if (!cPkts) 2436 2437 { 2437 LogFunc(("%s No packets to send found on %s\n", pThis->szInst, pTx Queue->szName));2438 LogFunc(("%s No packets to send found on %s\n", pThis->szInst, pTxVirtq->szName)); 2438 2439 2439 2440 if (pDrv) … … 2449 2450 int rc; 2450 2451 PVIRTIO_DESC_CHAIN_T pDescChain = NULL; 2451 while ((rc = virtioCoreR3 QueuePeek(pVirtio->pDevInsR3, pVirtio, pTxQueue->idx, &pDescChain)) == VINF_SUCCESS)2452 { 2453 Log10Func(("%s fetched descriptor chain from %s\n", pThis->szInst, pTx Queue->szName));2452 while ((rc = virtioCoreR3VirtqPeek(pVirtio->pDevInsR3, pVirtio, pTxVirtq->idx, &pDescChain)) == VINF_SUCCESS) 2453 { 2454 Log10Func(("%s fetched descriptor chain from %s\n", pThis->szInst, pTxVirtq->szName)); 2454 2455 2455 2456 PVIRTIOSGBUF pSgPhysSend = pDescChain->pSgPhysSend; … … 2535 2536 2536 2537 /* Remove this descriptor chain from the available ring */ 2537 virtioCoreR3 QueueSkip(pVirtio, pTxQueue->idx);2538 virtioCoreR3VirtqSkip(pVirtio, pTxVirtq->idx); 2538 2539 2539 2540 /* No data to return to guest, but call is needed put elem (e.g. desc chain) on used ring */ 2540 virtioCoreR3 QueuePut(pVirtio->pDevInsR3, pVirtio, pTxQueue->idx, NULL, pDescChain, true /* fFence */);2541 virtioCoreR3VirtqPut(pVirtio->pDevInsR3, pVirtio, pTxVirtq->idx, NULL, pDescChain, true /* fFence */); 2541 2542 2542 2543 /* Update used ring idx and notify guest that we've transmitted the data it sent */ 2543 virtioCore QueueSync(pVirtio->pDevInsR3, pVirtio, pTxQueue->idx);2544 virtioCoreVirtqSync(pVirtio->pDevInsR3, pVirtio, pTxVirtq->idx); 2544 2545 } 2545 2546 … … 2564 2565 PPDMDEVINS pDevIns = pThisCC->pDevIns; 2565 2566 PVIRTIONET pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVIRTIONET); 2566 PVIRTIONET QUEUE pTxQueue = &pThis->aQueues[TXQIDX(0)];2567 PVIRTIONETVIRTQ pTxVirtq = &pThis->aVirtqs[TXQIDX(0)]; 2567 2568 STAM_COUNTER_INC(&pThis->StatTransmitByNetwork); 2568 2569 2569 2570 /** @todo If we ever start using more than one Rx/Tx queue pair, is a random queue 2570 2571 selection algorithm feasible or even necessary */ 2571 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pTx Queue, true /*fOnWorkerThread*/);2572 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pTxVirtq, true /*fOnWorkerThread*/); 2572 2573 } 2573 2574 … … 2745 2746 static int virtioNetR3CreateOneWorkerThread(PPDMDEVINS pDevIns, PVIRTIONET pThis, uint16_t idxWorker, 2746 2747 PVIRTIONETWORKER pWorker, PVIRTIONETWORKERR3 pWorkerR3, 2747 PVIRTIONET QUEUE pQueue)2748 PVIRTIONETVIRTQ pVirtq) 2748 2749 { 2749 2750 Log10Func(("%s\n", pThis->szInst)); 2751 RT_NOREF(pThis); 2750 2752 2751 2753 int rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pWorker->hEvtProcess); … … 2755 2757 N_("DevVirtioNET: Failed to create SUP event semaphore")); 2756 2758 2757 LogFunc(("creating thread for queue %s\n", p Queue->szName));2759 LogFunc(("creating thread for queue %s\n", pVirtq->szName)); 2758 2760 2759 2761 rc = PDMDevHlpThreadCreate(pDevIns, &pWorkerR3->pThread, 2760 2762 (void *)pWorker, virtioNetR3WorkerThread, 2761 virtioNetR3WakeupWorker, 0, RTTHREADTYPE_IO, p Queue->szName);2763 virtioNetR3WakeupWorker, 0, RTTHREADTYPE_IO, pVirtq->szName); 2762 2764 if (RT_FAILURE(rc)) 2763 2765 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 2764 N_("Error creating thread for Virtual Queue %s\n"), pQueue->idx);2765 2766 pWorker->p Queue = pWorkerR3->pQueue = pQueue;2767 pWorker->idx = pWorkerR3->idx = idxWorker;2768 p Queue->pWorker = pWorker;2769 p Queue->pWorkerR3 = pWorkerR3;2766 N_("Error creating thread for Virtual Virtq %s\n"), pVirtq->idx); 2767 2768 pWorker->pVirtq = pWorkerR3->pVirtq = pVirtq; 2769 pWorker->idx = pWorkerR3->idx = idxWorker; 2770 pVirtq->pWorker = pWorker; 2771 pVirtq->pWorkerR3 = pWorkerR3; 2770 2772 pWorker->fAssigned = true; 2771 2773 2772 LogFunc(("%s pThread: %p\n", p Queue->szName, pWorkerR3->pThread));2774 LogFunc(("%s pThread: %p\n", pVirtq->szName, pWorkerR3->pThread)); 2773 2775 2774 2776 return rc; … … 2782 2784 Log10Func(("%s\n", pThis->szInst)); 2783 2785 2784 PVIRTIONET QUEUE pCtlQueue = &pThis->aQueues[CTRLQIDX];2786 PVIRTIONETVIRTQ pCtlVirtq = &pThis->aVirtqs[CTRLQIDX]; 2785 2787 int rc = virtioNetR3CreateOneWorkerThread(pDevIns, pThis, CTRLQIDX /* idxWorker */, 2786 &pThis->aWorkers[CTRLWIDX], &pThisCC->aWorkers[CTRLWIDX], pCtl Queue);2788 &pThis->aWorkers[CTRLWIDX], &pThisCC->aWorkers[CTRLWIDX], pCtlVirtq); 2787 2789 AssertRCReturn(rc, rc); 2788 2790 2789 pCtl Queue->fHasWorker = true;2791 pCtlVirtq->fHasWorker = true; 2790 2792 2791 2793 uint16_t idxWorker = CTRLWIDX + 1; 2792 for (uint16_t idx QueuePair = 0; idxQueuePair < pThis->cVirtqPairs; idxQueuePair++, idxWorker++)2793 { 2794 PVIRTIONET QUEUE pTxQueue = &pThis->aQueues[TXQIDX(idxQueuePair)];2795 PVIRTIONET QUEUE pRxQueue = &pThis->aQueues[RXQIDX(idxQueuePair)];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 2798 2797 2799 rc = virtioNetR3CreateOneWorkerThread(pDevIns, pThis, idxWorker, &pThis->aWorkers[idxWorker], 2798 &pThisCC->aWorkers[idxWorker], pTx Queue);2800 &pThisCC->aWorkers[idxWorker], pTxVirtq); 2799 2801 AssertRCReturn(rc, rc); 2800 2802 2801 pTx Queue->fHasWorker = true;2802 pRx Queue->fHasWorker = false;2803 } 2804 pThis->cWorkers = pThis->cVirtqPairs + 1 ;2803 pTxVirtq->fHasWorker = true; 2804 pRxVirtq->fHasWorker = false; 2805 } 2806 pThis->cWorkers = pThis->cVirtqPairs + 1 /* Control virtq */; 2805 2807 return rc; 2806 2808 } … … 2814 2816 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 2815 2817 PVIRTIONETWORKER pWorker = (PVIRTIONETWORKER)pThread->pvUser; 2816 PVIRTIONET QUEUE pQueue = pWorker->pQueue;2818 PVIRTIONETVIRTQ pVirtq = pWorker->pVirtq; 2817 2819 2818 2820 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 2819 2821 return VINF_SUCCESS; 2820 2822 2821 LogFunc(("%s worker thread started for %s\n", pThis->szInst, pQueue->szName)); 2822 2823 /** @todo Race w/guest enabling/disabling guest notifications cyclically. 2824 See BugRef #8651, Comment #82 */ 2825 2826 virtioCoreQueueNotifyEnable(&pThis->Virtio, pQueue->idx, true /* fEnable */); 2823 LogFunc(("%s worker thread started for %s\n", pThis->szInst, pVirtq->szName)); 2824 2825 /** @todo Race w/guest enabling/disabling guest notifications cyclically. 2826 See BugRef #8651, Comment #82 */ 2827 virtioCoreVirtqNotifyEnable(&pThis->Virtio, pVirtq->idx, true /* fEnable */); 2827 2828 2828 2829 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 2829 2830 { 2830 if (IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, p Queue->idx))2831 if (IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, pVirtq->idx)) 2831 2832 { 2832 2833 /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */ … … 2835 2836 if (!fNotificationSent) 2836 2837 { 2837 Log10Func(("%s %s worker sleeping...\n\n", pThis->szInst, p Queue->szName));2838 Log10Func(("%s %s worker sleeping...\n\n", pThis->szInst, pVirtq->szName)); 2838 2839 Assert(ASMAtomicReadBool(&pWorker->fSleeping)); 2839 2840 int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pWorker->hEvtProcess, RT_INDEFINITE_WAIT); … … 2853 2854 if (!pThisCC->fQuiescing) 2854 2855 { 2855 if (p Queue->fCtlQueue)2856 if (pVirtq->fCtlVirtq) 2856 2857 { 2857 Log10Func(("%s %s worker woken. Fetching desc chain\n", pThis->szInst, p Queue->szName));2858 Log10Func(("%s %s worker woken. Fetching desc chain\n", pThis->szInst, pVirtq->szName)); 2858 2859 PVIRTIO_DESC_CHAIN_T pDescChain = NULL; 2859 int rc = virtioCoreR3 QueueGet(pDevIns, &pThis->Virtio, pQueue->idx, &pDescChain, true);2860 int rc = virtioCoreR3VirtqGet(pDevIns, &pThis->Virtio, pVirtq->idx, &pDescChain, true); 2860 2861 if (rc == VERR_NOT_AVAILABLE) 2861 2862 { 2862 Log10Func(("%s %s worker woken. Nothing found in queue/n", pThis->szInst, p Queue->szName));2863 Log10Func(("%s %s worker woken. Nothing found in queue/n", pThis->szInst, pVirtq->szName)); 2863 2864 continue; 2864 2865 } … … 2868 2869 else /* Must be Tx queue */ 2869 2870 { 2870 Log10Func(("%s %s worker woken. Queue has data to transmit\n", pThis->szInst, pQueue->szName));2871 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, p Queue, false /* fOnWorkerThread */);2871 Log10Func(("%s %s worker woken. Virtq has data to transmit\n", pThis->szInst, pVirtq->szName)); 2872 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pVirtq, false /* fOnWorkerThread */); 2872 2873 } 2873 2874 2874 2875 /* Rx queues aren't handled by our worker threads. Instead, the PDM network 2875 2876 * leaf driver invokes PDMINETWORKDOWN.pfnWaitReceiveAvail() callback, 2876 * which waits until notified directly by virtioNet QueueNotified()2877 * which waits until notified directly by virtioNetVirtqNotified() 2877 2878 * that guest IN buffers have been added to receive virt queue. 2878 2879 */ 2879 2880 } 2880 2881 } 2881 Log10(("%s %s worker thread exiting\n", pThis->szInst, p Queue->szName));2882 Log10(("%s %s worker thread exiting\n", pThis->szInst, pVirtq->szName)); 2882 2883 return VINF_SUCCESS; 2883 2884 } … … 2898 2899 pThis->szInst)); 2899 2900 2900 pThis->fNegotiatedFeatures = virtioCoreGet AcceptedFeatures(pVirtio);2901 pThis->fNegotiatedFeatures = virtioCoreGetNegotiatedFeatures(pVirtio); 2901 2902 2902 2903 #ifdef LOG_ENABLED … … 2910 2911 pThisCC->fQuiescing = false; 2911 2912 2912 for (unsigned idx Queue = 0; idxQueue < pThis->cVirtQueues; idxQueue++)2913 for (unsigned idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++) 2913 2914 { 2914 PVIRTIONET QUEUE pQueue = &pThis->aQueues[idxQueue];2915 p Queue->idx = idxQueue;2916 (void) virtioCoreR3 QueueAttach(&pThis->Virtio, pQueue->idx, pQueue->szName);2917 p Queue->fAttachedToVirtioCore = true;2918 if (IS_VIRTQ_EMPTY(pThisCC->pDevIns, &pThis->Virtio, p Queue->idx))2919 virtioCore QueueNotifyEnable(&pThis->Virtio, pQueue->idx, true /* fEnable */);2915 PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[idxVirtq]; 2916 pVirtq->idx = idxVirtq; 2917 (void) virtioCoreR3VirtqAttach(&pThis->Virtio, pVirtq->idx, pVirtq->szName); 2918 pVirtq->fAttachedToVirtioCore = true; 2919 if (IS_VIRTQ_EMPTY(pThisCC->pDevIns, &pThis->Virtio, pVirtq->idx)) 2920 virtioCoreVirtqNotifyEnable(&pThis->Virtio, pVirtq->idx, true /* fEnable */); 2920 2921 } 2921 2922 } … … 2943 2944 pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, true); 2944 2945 2945 for (uint16_t idx Queue = 0; idxQueue < pThis->cVirtQueues; idxQueue++)2946 pThis->a Queues[idxQueue].fAttachedToVirtioCore = false;2946 for (uint16_t idxVirtq = 0; idxVirtq < pThis->cVirtVirtqs; idxVirtq++) 2947 pThis->aVirtqs[idxVirtq].fAttachedToVirtioCore = false; 2947 2948 } 2948 2949 } … … 3153 3154 3154 3155 /* Initialize the generic Virtio core: */ 3155 pThisCC->Virtio.pfn QueueNotified = virtioNetQueueNotified;3156 pThisCC->Virtio.pfnVirtqNotified = virtioNetVirtqNotified; 3156 3157 pThisCC->Virtio.pfnStatusChanged = virtioNetR3StatusChanged; 3157 3158 pThisCC->Virtio.pfnDevCapRead = virtioNetR3DevCapRead; … … 3192 3193 ? pThis->virtioNetConfig.uMaxVirtqPairs : 1; 3193 3194 3194 pThis->cVirt Queues += pThis->cVirtqPairs * 2 + 1;3195 pThis->cVirtVirtqs += pThis->cVirtqPairs * 2 + 1; 3195 3196 3196 3197 /* Create Link Up Timer */ … … 3202 3203 */ 3203 3204 virtioNetR3SetVirtqNames(pThis); 3204 pThis->a Queues[CTRLQIDX].fCtlQueue= true;3205 pThis->aVirtqs[CTRLQIDX].fCtlVirtq = true; 3205 3206 3206 3207 /* … … 3290 3291 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 3291 3292 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 3292 pThisCC->Virtio.pfn QueueNotified = virtioNetQueueNotified;3293 pThisCC->Virtio.pfnVirtqNotified = virtioNetVirtqNotified; 3293 3294 return virtioCoreRZInit(pDevIns, &pThis->Virtio); 3294 3295 }
Note:
See TracChangeset
for help on using the changeset viewer.