Changeset 84774 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Jun 11, 2020 6:01:00 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 138574
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp
r84468 r84774 59 59 #include "VBoxDD.h" 60 60 61 /* After debugging single instance case, restore instance name logging */62 #define INSTANCE(pState) (char *)(pState->szInstanceName ? pState->szInstanceName : "") // Avoid requiring RT_NOREF in some funcs63 64 61 #define VIRTIONET_SAVED_STATE_VERSION UINT32_C(1) 65 62 #define VIRTIONET_MAX_QPAIRS 1 … … 70 67 #define VIRTIONET_PREALLOCATE_RX_SEG_COUNT 32 71 68 72 #define VIRTQNAME(idxQueue) (pThis->a szVirtqNames[idxQueue])69 #define VIRTQNAME(idxQueue) (pThis->aQueues[idxQueue]->szName) 73 70 #define CBVIRTQNAME(idxQueue) RTStrNLen(VIRTQNAME(idxQueue), sizeof(VIRTQNAME(idxQueue))) 74 71 #define FEATURE_ENABLED(feature) RT_BOOL(pThis->fNegotiatedFeatures & VIRTIONET_F_##feature) 75 72 #define FEATURE_DISABLED(feature) (!FEATURE_ENABLED(feature)) 76 73 #define FEATURE_OFFERED(feature) VIRTIONET_HOST_FEATURES_OFFERED & VIRTIONET_F_##feature 74 75 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, idxQueue) \ 76 (virtioCoreQueueAvailCount(pDevIns, pVirtio, idxQueue) == 0) 77 77 78 78 #define SET_LINK_UP(pState) \ … … 301 301 302 302 /** 303 * device-specific queue info 304 */ 305 struct VIRTIONETWORKER; 306 struct VIRTIONETWORKERR3; 307 308 typedef struct VIRTIONETQUEUE 309 { 310 struct VIRTIONETWORKER *pWorker; /**< Pointer to R0 worker struct */ 311 struct VIRTIONETWORKERR3 *pWorkerR3; /**< Pointer to R3 worker struct */ 312 uint16_t idx; /**< Index of this queue */ 313 uint16_t align; 314 char szName[VIRTIO_MAX_QUEUE_NAME_SIZE]; /**< Queue name */ 315 bool fCtlQueue; /**< If set this queue is the control queue */ 316 bool fHasWorker; /**< If set this queue has an associated worker */ 317 bool fAttachedToVirtioCore; /**< Set if queue attached to virtio core */ 318 uint8_t pad; 319 } VIRTIONETQUEUE, *PVIRTIONETQUEUE; 320 321 /** 303 322 * Worker thread context, shared state. 304 323 */ … … 306 325 { 307 326 SUPSEMEVENT hEvtProcess; /**< handle of associated sleep/wake-up semaphore */ 327 PVIRTIONETQUEUE pQueue; /**< pointer to queue */ 328 uint16_t idx; /**< Index of this worker */ 308 329 bool volatile fSleeping; /**< Flags whether worker thread is sleeping or not */ 309 330 bool volatile fNotified; /**< Flags whether worker thread notified */ 331 bool fAssigned; /**< Flags whether worker thread has been set up */ 332 uint8_t pad; 310 333 } VIRTIONETWORKER; 311 /** Pointer to a VirtIO SCSIworker. */334 /** Pointer to a virtio net worker. */ 312 335 typedef VIRTIONETWORKER *PVIRTIONETWORKER; 313 336 … … 318 341 { 319 342 R3PTRTYPE(PPDMTHREAD) pThread; /**< pointer to worker thread's handle */ 320 uint16_t idxQueue; /**< Index of associated queue */ 343 PVIRTIONETQUEUE pQueue; /**< pointer to queue */ 344 uint16_t idx; /**< Index of this worker */ 345 uint16_t pad; 321 346 } VIRTIONETWORKERR3; 322 /** Pointer to a VirtIO SCSIworker. */347 /** Pointer to a virtio net worker. */ 323 348 typedef VIRTIONETWORKERR3 *PVIRTIONETWORKERR3; 324 349 … … 340 365 341 366 /** Track which VirtIO queues we've attached to */ 342 bool afQueueAttached[VIRTIONET_MAX_QUEUES]; 343 344 /** Device-specific spec-based VirtIO VIRTQNAMEs */ 345 char aszVirtqNames[VIRTIONET_MAX_QUEUES][VIRTIO_MAX_QUEUE_NAME_SIZE]; 346 347 /** Instance name */ 348 char szInstanceName[16]; 349 367 VIRTIONETQUEUE aQueues[VIRTIONET_MAX_QUEUES]; 368 369 /** PDM device Instance name */ 370 char szInst[16]; 371 372 /** VirtIO features negotiated with the guest, including generic core and device specific */ 373 uint64_t fNegotiatedFeatures; 374 375 /** Number of Rx/Tx queue pairs (only one if MQ feature not negotiated */ 350 376 uint16_t cVirtqPairs; 351 377 378 /** Number of virtqueues total (which includes each queue of each pair plus one control queue */ 352 379 uint16_t cVirtQueues; 353 380 381 /** Number of worker threads (one for the control queue and one for each Tx queue) */ 354 382 uint16_t cWorkers; 355 383 356 uint64_t fNegotiatedFeatures; 357 358 SUPSEMEVENT hTxEvent; 384 /** Alighnment */ 385 uint16_t alignment; 359 386 360 387 /** Indicates transmission in progress -- only one thread is allowed. */ 361 388 uint32_t uIsTransmitting; 362 389 390 /** virtio-net-1-dot-0 (in milliseconds). */ 391 uint32_t cMsLinkUpDelay; 392 393 /** The number of actually used slots in aMacMulticastFilter. */ 394 uint32_t cMulticastFilterMacs; 395 396 /** The number of actually used slots in aMacUniicastFilter. */ 397 uint32_t cUnicastFilterMacs; 398 399 /** Semaphore leaf device's thread waits on until guest driver sends empty Rx bufs */ 400 SUPSEMEVENT hEventRxDescAvail; 401 402 /** Array of MAC multicast addresses accepted by RX filter. */ 403 RTMAC aMacMulticastFilter[VIRTIONET_MAC_FILTER_LEN]; 404 405 /** Array of MAC unicast addresses accepted by RX filter. */ 406 RTMAC aMacUnicastFilter[VIRTIONET_MAC_FILTER_LEN]; 407 408 /** Default MAC address which rx filtering accepts */ 409 RTMAC rxFilterMacDefault; 410 363 411 /** MAC address obtained from the configuration. */ 364 412 RTMAC macConfigured; 365 413 366 /** Default MAC address which rx filtering accepts */ 367 RTMAC rxFilterMacDefault; 414 /** Bit array of VLAN filter, one bit per VLAN ID. */ 415 uint8_t aVlanFilter[VIRTIONET_MAX_VLAN_ID / sizeof(uint8_t)]; 416 417 /** Set if PDM leaf device at the network interface is starved for Rx buffers */ 418 bool volatile fLeafWantsEmptyRxBufs; 419 420 /** Number of packet being sent/received to show in debug log. */ 421 uint32_t uPktNo; 422 423 /** Flags whether VirtIO core is in ready state */ 424 uint8_t fVirtioReady; 425 426 /** Resetting flag */ 427 uint8_t fResetting; 428 429 /** Quiescing I/O activity flag */ 430 uint8_t fQuiescing; 431 432 /** Promiscuous mode -- RX filter accepts all packets. */ 433 uint8_t fPromiscuous; 434 435 /** All multicast mode -- RX filter accepts all multicast packets. */ 436 uint8_t fAllMulticast; 437 438 /** All unicast mode -- RX filter accepts all unicast packets. */ 439 uint8_t fAllUnicast; 440 441 /** No multicast mode - Supresses multicast receive */ 442 uint8_t fNoMulticast; 443 444 /** No unicast mode - Suppresses unicast receive */ 445 uint8_t fNoUnicast; 446 447 /** No broadcast mode - Supresses broadcast receive */ 448 uint8_t fNoBroadcast; 368 449 369 450 /** True if physical cable is attached in configuration. */ 370 451 bool fCableConnected; 371 372 /** virtio-net-1-dot-0 (in milliseconds). */373 uint32_t cMsLinkUpDelay;374 375 uint32_t alignment;376 377 /** Number of packet being sent/received to show in debug log. */378 uint32_t uPktNo;379 380 /** N/A: */381 bool volatile fLeafWantsRxBuffers;382 383 SUPSEMEVENT hEventRxDescAvail;384 385 /** Flags whether VirtIO core is in ready state */386 uint8_t fVirtioReady;387 388 /** Resetting flag */389 uint8_t fResetting;390 391 /** Quiescing I/O activity flag */392 uint8_t fQuiescing;393 394 /** Promiscuous mode -- RX filter accepts all packets. */395 uint8_t fPromiscuous;396 397 /** All multicast mode -- RX filter accepts all multicast packets. */398 uint8_t fAllMulticast;399 400 /** All unicast mode -- RX filter accepts all unicast packets. */401 uint8_t fAllUnicast;402 403 /** No multicast mode - Supresses multicast receive */404 uint8_t fNoMulticast;405 406 /** No unicast mode - Suppresses unicast receive */407 uint8_t fNoUnicast;408 409 /** No broadcast mode - Supresses broadcast receive */410 uint8_t fNoBroadcast;411 412 /** The number of actually used slots in aMacMulticastFilter. */413 uint32_t cMulticastFilterMacs;414 415 /** Array of MAC multicast addresses accepted by RX filter. */416 RTMAC aMacMulticastFilter[VIRTIONET_MAC_FILTER_LEN];417 418 /** The number of actually used slots in aMacUniicastFilter. */419 uint32_t cUnicastFilterMacs;420 421 /** Array of MAC unicast addresses accepted by RX filter. */422 RTMAC aMacUnicastFilter[VIRTIONET_MAC_FILTER_LEN];423 424 /** Bit array of VLAN filter, one bit per VLAN ID. */425 uint8_t aVlanFilter[VIRTIONET_MAX_VLAN_ID / sizeof(uint8_t)];426 452 427 453 /** @name Statistic … … 489 515 R3PTRTYPE(PPDMINETWORKUP) pDrv; 490 516 491 R3PTRTYPE(PPDMTHREAD) pTxThread;492 493 517 /** Link Up(/Restore) Timer. */ 494 518 TMTIMERHANDLE hLinkUpTimer; 495 496 /** Queue to send tasks to R3. - HC ptr */497 R3PTRTYPE(PPDMQUEUE) pNotifierQueueR3;498 519 499 520 /** True if in the process of quiescing I/O */ … … 541 562 typedef CTX_SUFF(PVIRTIONET) PVIRTIONETCC; 542 563 564 #ifdef IN_RING3 565 static DECLCALLBACK(int) virtioNetR3WorkerThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread); 566 567 DECLINLINE(const char *) virtioNetThreadStateName(PPDMTHREAD pThread) 568 { 569 if (!pThread) 570 return "<null>"; 571 572 switch(pThread->enmState) 573 { 574 case PDMTHREADSTATE_INVALID: 575 return "invalid state"; 576 case PDMTHREADSTATE_INITIALIZING: 577 return "initializing"; 578 case PDMTHREADSTATE_SUSPENDING: 579 return "suspending"; 580 case PDMTHREADSTATE_SUSPENDED: 581 return "suspended"; 582 case PDMTHREADSTATE_RESUMING: 583 return "resuming"; 584 case PDMTHREADSTATE_RUNNING: 585 return "running"; 586 case PDMTHREADSTATE_TERMINATING: 587 return "terminating"; 588 case PDMTHREADSTATE_TERMINATED: 589 return "terminated"; 590 default: 591 return "unknown state"; 592 } 593 } 594 #endif 595 543 596 /** 544 597 * Wakeup the RX thread. … … 551 604 552 605 STAM_COUNTER_INC(&pThis->StatRxOverflowWakeup); 553 554 Log10Func(("%s Waking downstream driver's Rx buf waiter thread\n", INSTANCE(pThis))); 555 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEventRxDescAvail); 556 AssertRC(rc); 606 if (pThis->hEventRxDescAvail != NIL_SUPSEMEVENT) 607 { 608 Log10Func(("%s Waking downstream device's Rx buf waiter thread\n", pThis->szInst)); 609 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEventRxDescAvail); 610 AssertRC(rc); 611 } 557 612 } 558 613 … … 565 620 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 566 621 567 uint16_t idxWorker; 568 if (idxQueue == CTRLQIDX) 569 idxWorker = pThis->cWorkers - 1; 570 else 571 idxWorker = idxQueue / 2; 572 573 PVIRTIONETWORKER pWorker = &pThis->aWorkers[idxWorker]; 574 AssertReturnVoid(idxQueue < pThis->cVirtQueues); 622 PVIRTIONETQUEUE pQueue = &pThis->aQueues[idxQueue]; 623 PVIRTIONETWORKER pWorker = pQueue->pWorker; 575 624 576 625 #if defined (IN_RING3) && defined (LOG_ENABLED) … … 578 627 #endif 579 628 580 Log10Func(("%s %s has available buffers\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));581 582 629 if (IS_RX_QUEUE(idxQueue)) 583 630 { 584 Log10Func(("%s Receive buffers have been added, waking Rx thread.\n", 585 INSTANCE(pThis))); 586 virtioNetWakeupRxBufWaiter(pDevIns); 587 } 588 else 631 uint16_t cBufsAvailable = virtioCoreQueueAvailCount(pDevIns, pVirtio, idxQueue); 632 633 if (cBufsAvailable) 634 { 635 Log10Func(("%s %u empty bufs added to %s by guest (notifying leaf device)\n", 636 pThis->szInst, cBufsAvailable, pQueue->szName)); 637 virtioNetWakeupRxBufWaiter(pDevIns); 638 } 639 else 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, pQueue->szName)); 642 } 643 else if (IS_TX_QUEUE(idxQueue) || IS_CTRL_QUEUE(idxQueue)) 589 644 { 590 645 /* Wake queue's worker thread up if sleeping (e.g. a Tx queue, or the control queue */ … … 593 648 if (ASMAtomicReadBool(&pWorker->fSleeping)) 594 649 { 595 Log10Func(("%s waking %s worker.\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));650 Log10Func(("%s %s has available buffers - waking worker.\n", pThis->szInst, pQueue->szName)); 596 651 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess); 597 652 AssertRC(rc); 598 653 } 654 else 655 { 656 Log10Func(("%s %s has available buffers - worker already awake\n", pThis->szInst, pQueue->szName)); 657 } 599 658 } 600 } 659 else 660 { 661 Log10Func(("%s %s has available buffers - waking worker.\n", pThis->szInst, pQueue->szName)); 662 } 663 } 664 else 665 LogRelFunc(("%s unrecognized queue %s (idx=%d) notified\n", pQueue->szName, idxQueue)); 601 666 } 602 667 … … 608 673 static DECLCALLBACK(int) virtioNetR3WakeupWorker(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 609 674 { 610 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 611 Log10Func(("%s\n", INSTANCE(pThis))); 612 return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[(uintptr_t)pThread->pvUser].hEvtProcess); 675 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 676 PVIRTIONETWORKER pWorker = (PVIRTIONETWORKER)pThread->pvUser; 677 678 Log10Func(("%s\n", pThis->szInst)); 679 680 return PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess); 613 681 } 614 682 … … 616 684 DECLINLINE(void) virtioNetR3SetVirtqNames(PVIRTIONET pThis) 617 685 { 686 RTStrCopy(pThis->aQueues[CTRLQIDX].szName, VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq"); 618 687 for (uint16_t qPairIdx = 0; qPairIdx < pThis->cVirtqPairs; qPairIdx++) 619 688 { 620 RTStrPrintf(pThis->aszVirtqNames[RXQIDX(qPairIdx)], VIRTIO_MAX_QUEUE_NAME_SIZE, "receiveq<%d>", qPairIdx); 621 RTStrPrintf(pThis->aszVirtqNames[TXQIDX(qPairIdx)], VIRTIO_MAX_QUEUE_NAME_SIZE, "transmitq<%d>", qPairIdx); 622 } 623 RTStrCopy(pThis->aszVirtqNames[CTRLQIDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq"); 689 RTStrPrintf(pThis->aQueues[RXQIDX(qPairIdx)].szName, VIRTIO_MAX_QUEUE_NAME_SIZE, "receiveq<%d>", qPairIdx); 690 RTStrPrintf(pThis->aQueues[TXQIDX(qPairIdx)].szName, VIRTIO_MAX_QUEUE_NAME_SIZE, "transmitq<%d>", qPairIdx); 691 } 624 692 } 625 693 … … 637 705 return; 638 706 639 vboxEthPacketDump(INSTANCE(pThis), pszText, pbPacket, (uint32_t)cb); 640 } 641 642 #ifdef LOG_ENABLED 643 644 void virtioNetDumpGcPhysRxBuf(PPDMDEVINS pDevIns, PVIRTIONET_PKT_HDR_T pRxPktHdr, 645 uint16_t cDescs, uint8_t *pvBuf, uint16_t cb, RTGCPHYS gcPhysRxBuf, uint8_t cbRxBuf) 646 { 647 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 648 pRxPktHdr->uNumBuffers = cDescs; 649 if (pRxPktHdr) 650 { 651 LogFunc(("-------------------------------------------------------------------\n")); 652 LogFunc(("rxPktHdr\n" 653 " uFlags ......... %2.2x\n" 654 " uGsoType ....... %2.2x\n" 655 " uHdrLen ........ %4.4x\n" 656 " uGsoSize ....... %4.4x\n" 657 " uChksumStart ... %4.4x\n" 658 " uChksumOffset .. %4.4x\n" 659 " uNumBuffers .... %4.4x\n", 660 pRxPktHdr->uFlags, 661 pRxPktHdr->uGsoType, pRxPktHdr->uHdrLen, pRxPktHdr->uGsoSize, 662 pRxPktHdr->uChksumStart, pRxPktHdr->uChksumOffset, pRxPktHdr->uNumBuffers)); 663 664 virtioCoreHexDump((uint8_t *)pRxPktHdr, sizeof(VIRTIONET_PKT_HDR_T), 0, "Dump of virtual rPktHdr"); 665 } 666 virtioNetR3PacketDump(pThis, (const uint8_t *)pvBuf, cb, "<-- Incoming"); 667 LogFunc((". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n")); 668 virtioCoreGcPhysHexDump(pDevIns, gcPhysRxBuf, cbRxBuf, 0, "Phys Mem Dump of Rx pkt"); 669 LogFunc(("-------------------------------------------------------------------\n")); 670 } 671 672 DECLINLINE(void) virtioNetPrintFeatures(VIRTIONET *pThis) 707 vboxEthPacketDump(pThis->szInst, pszText, pbPacket, (uint32_t)cb); 708 } 709 710 DECLINLINE(void) virtioNetPrintFeatures(VIRTIONET *pThis, PCDBGFINFOHLP pHlp) 673 711 { 674 712 static struct … … 714 752 isOffered ? "+" : "-", isNegotiated ? "x" : " ", s_aFeatures[i].pcszDesc); 715 753 } 716 Log3(("VirtIO Net Features Configuration\n\n" 717 " Offered Accepted Feature Description\n" 718 " ------- -------- ------- -----------\n" 719 "%s\n", pszBuf)); 754 if (pHlp) 755 pHlp->pfnPrintf(pHlp, "VirtIO Net Features Configuration\n\n" 756 " Offered Accepted Feature Description\n" 757 " ------- -------- ------- -----------\n" 758 "%s\n", pszBuf); 759 #ifdef LOG_ENABLED 760 else 761 Log3(("VirtIO Net Features Configuration\n\n" 762 " Offered Accepted Feature Description\n" 763 " ------- -------- ------- -----------\n" 764 "%s\n", pszBuf)); 765 #endif 720 766 RTMemFree(pszBuf); 721 767 } 768 769 #ifdef LOG_ENABLED 770 void virtioNetDumpGcPhysRxBuf(PPDMDEVINS pDevIns, PVIRTIONET_PKT_HDR_T pRxPktHdr, 771 uint16_t cDescs, uint8_t *pvBuf, uint16_t cb, RTGCPHYS GCPhysRxBuf, uint8_t cbRxBuf) 772 { 773 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 774 pRxPktHdr->uNumBuffers = cDescs; 775 if (pRxPktHdr) 776 { 777 LogFunc(("-------------------------------------------------------------------\n")); 778 LogFunc(("rxPktHdr\n" 779 " uFlags ......... %2.2x\n" 780 " uGsoType ....... %2.2x\n" 781 " uHdrLen ........ %4.4x\n" 782 " uGsoSize ....... %4.4x\n" 783 " uChksumStart ... %4.4x\n" 784 " uChksumOffset .. %4.4x\n" 785 " uNumBuffers .... %4.4x\n", 786 pRxPktHdr->uFlags, 787 pRxPktHdr->uGsoType, pRxPktHdr->uHdrLen, pRxPktHdr->uGsoSize, 788 pRxPktHdr->uChksumStart, pRxPktHdr->uChksumOffset, pRxPktHdr->uNumBuffers)); 789 790 virtioCoreHexDump((uint8_t *)pRxPktHdr, sizeof(VIRTIONET_PKT_HDR_T), 0, "Dump of virtual rPktHdr"); 791 } 792 virtioNetR3PacketDump(pThis, (const uint8_t *)pvBuf, cb, "<-- Incoming"); 793 LogFunc((". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n")); 794 795 virtioCoreGCPhysHexDump(pDevIns, GCPhysRxBuf, cbRxBuf, 0, "Phys Mem Dump of Rx pkt"); 796 LogFunc(("-------------------------------------------------------------------\n")); 797 } 798 722 799 #endif /* LOG_ENABLED */ 800 801 /** 802 * @callback_method_impl{FNDBGFHANDLERDEV, virtio-net debugger info callback.} 803 */ 804 static DECLCALLBACK(void) virtioNetR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) 805 { 806 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 807 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 808 809 bool fNone = pszArgs && *pszArgs == '\0'; 810 bool fAll = pszArgs && (*pszArgs == 'a' || *pszArgs == 'A'); /* "all" */ 811 bool fNetwork = pszArgs && (*pszArgs == 'n' || *pszArgs == 'N'); /* "network" */ 812 bool fFeatures = pszArgs && (*pszArgs == 'f' || *pszArgs == 'F'); /* "features" */ 813 bool fState = pszArgs && (*pszArgs == 's' || *pszArgs == 'S'); /* "state" */ 814 bool fPointers = pszArgs && (*pszArgs == 'p' || *pszArgs == 'P'); /* "pointers" */ 815 bool fQueues = pszArgs && (*pszArgs == 'q' || *pszArgs == 'Q'); /* "queues */ 816 817 /* Show basic information. */ 818 pHlp->pfnPrintf(pHlp, 819 "\n" 820 "---------------------------------------------------------------------------\n" 821 "Debug Info: %s\n" 822 " (options: [a]ll, [n]et, [f]eatures, [s]tate, [p]ointers, [q]ueues)\n" 823 "---------------------------------------------------------------------------\n\n", 824 pThis->szInst, pDevIns->pReg->szName); 825 826 if (fNone) 827 return; 828 829 /* Show offered/unoffered, accepted/rejected features */ 830 if (fAll || fFeatures) 831 { 832 virtioCorePrintFeatures(&pThis->Virtio, pHlp); 833 virtioNetPrintFeatures(pThis, pHlp); 834 pHlp->pfnPrintf(pHlp, "\n"); 835 } 836 837 /* Show queues (and associate worker info if applicable) */ 838 if (fAll || fQueues) 839 { 840 pHlp->pfnPrintf(pHlp, "Queue information:\n\n"); 841 842 for (int idxQueue = 0; idxQueue < pThis->cVirtQueues; idxQueue++) 843 { 844 PVIRTIONETQUEUE pQueue = &pThis->aQueues[idxQueue]; 845 846 if (pQueue->fHasWorker) 847 { 848 PVIRTIONETWORKER pWorker = pQueue->pWorker; 849 PVIRTIONETWORKERR3 pWorkerR3 = pQueue->pWorkerR3; 850 851 if (pWorker->fAssigned) 852 { 853 pHlp->pfnPrintf(pHlp, " %-15s (pThread: %p %s) ", 854 pQueue->szName, 855 pWorkerR3->pThread, 856 virtioNetThreadStateName(pWorkerR3->pThread)); 857 if (pQueue->fAttachedToVirtioCore) 858 { 859 pHlp->pfnPrintf(pHlp, "worker: "); 860 pHlp->pfnPrintf(pHlp, "%s", pWorker->fSleeping ? "blocking" : "unblocked"); 861 pHlp->pfnPrintf(pHlp, "%s", pWorker->fNotified ? ", notified" : ""); 862 } 863 else 864 if (pWorker->fNotified) 865 pHlp->pfnPrintf(pHlp, "not attached to virtio core"); 866 } 867 } 868 else 869 { 870 pHlp->pfnPrintf(pHlp, " %-15s (INetworkDown's thread) %s", pQueue->szName, 871 pQueue->fAttachedToVirtioCore ? "" : "not attached to virtio core"); 872 } 873 pHlp->pfnPrintf(pHlp, "\n"); 874 virtioCoreR3QueueInfo(pDevIns, pHlp, pszArgs, idxQueue); 875 pHlp->pfnPrintf(pHlp, " ---------------------------------------------------------------------\n"); 876 pHlp->pfnPrintf(pHlp, "\n"); 877 } 878 pHlp->pfnPrintf(pHlp, "\n"); 879 } 880 881 /* Show various pointers */ 882 if (fAll || fPointers) 883 { 884 885 pHlp->pfnPrintf(pHlp, "Internal pointers:\n\n"); 886 887 pHlp->pfnPrintf(pHlp, " pDevIns ................... %p\n", pDevIns); 888 pHlp->pfnPrintf(pHlp, " PVIRTIONET ................ %p\n", pThis); 889 pHlp->pfnPrintf(pHlp, " PVIRTIONETCC .............. %p\n", pThisCC); 890 pHlp->pfnPrintf(pHlp, " pDrvBase .................. %p\n", pThisCC->pDrvBase); 891 pHlp->pfnPrintf(pHlp, " pDrv ...................... %p\n", pThisCC->pDrv); 892 pHlp->pfnPrintf(pHlp, " pDrv ...................... %p\n", pThisCC->pDrv); 893 pHlp->pfnPrintf(pHlp, "\n"); 894 pHlp->pfnPrintf(pHlp, "Misc state\n"); 895 pHlp->pfnPrintf(pHlp, "\n"); 896 pHlp->pfnPrintf(pHlp, " fVirtioReady .............. %d\n", pThis->fVirtioReady); 897 pHlp->pfnPrintf(pHlp, " fGenUpdatePending ......... %d\n", pThis->Virtio.fGenUpdatePending); 898 pHlp->pfnPrintf(pHlp, " fMsiSupport ............... %d\n", pThis->Virtio.fMsiSupport); 899 pHlp->pfnPrintf(pHlp, " uConfigGeneration ......... %d\n", pThis->Virtio.uConfigGeneration); 900 pHlp->pfnPrintf(pHlp, " uDeviceStatus ............. 0x%x\n", pThis->Virtio.uDeviceStatus); 901 pHlp->pfnPrintf(pHlp, " cVirtqPairs .,............. %d\n", pThis->cVirtqPairs); 902 pHlp->pfnPrintf(pHlp, " cVirtQueues .,............. %d\n", pThis->cVirtQueues); 903 pHlp->pfnPrintf(pHlp, " cWorkers .................. %d\n", pThis->cWorkers); 904 pHlp->pfnPrintf(pHlp, " MMIO mapping name ......... %d\n", pThisCC->Virtio.pcszMmioName); 905 906 } 907 908 /* Show device state info */ 909 if (fAll || fState) 910 { 911 pHlp->pfnPrintf(pHlp, "Device state:\n\n"); 912 uint32_t fTransmitting = ASMAtomicReadU32(&pThis->uIsTransmitting); 913 914 pHlp->pfnPrintf(pHlp, " Transmitting: ............. %s\n", fTransmitting ? "true" : "false"); 915 pHlp->pfnPrintf(pHlp, " Quiescing: ................ %s %s\n", 916 pThis->fQuiescing ? "true" : "false", 917 pThis->fQuiescing ? "(" : "", 918 pThis->fQuiescing ? virtioCoreGetStateChangeText(pThisCC->enmQuiescingFor) : "", 919 pThis->fQuiescing ? ")" : ""); 920 pHlp->pfnPrintf(pHlp, " Resetting: ................ %s\n", pThis->fResetting ? "true" : "false"); 921 pHlp->pfnPrintf(pHlp, "\n"); 922 } 923 924 /* Show network related information */ 925 if (fAll || fNetwork) 926 { 927 pHlp->pfnPrintf(pHlp, "Network configuration:\n\n"); 928 929 pHlp->pfnPrintf(pHlp, " MAC: ...................... %RTmac\n", &pThis->macConfigured); 930 pHlp->pfnPrintf(pHlp, "\n"); 931 pHlp->pfnPrintf(pHlp, " Cable: .................... %s\n", pThis->fCableConnected ? "connected" : "disconnected"); 932 pHlp->pfnPrintf(pHlp, " Link-up delay: ............ %d ms\n", pThis->cMsLinkUpDelay); 933 pHlp->pfnPrintf(pHlp, "\n"); 934 pHlp->pfnPrintf(pHlp, " Accept all multicast: ..... %s\n", pThis->fAllMulticast ? "true" : "false"); 935 pHlp->pfnPrintf(pHlp, " Suppress broadcast: ....... %s\n", pThis->fNoBroadcast ? "true" : "false"); 936 pHlp->pfnPrintf(pHlp, " Suppress unicast: ......... %s\n", pThis->fNoUnicast ? "true" : "false"); 937 pHlp->pfnPrintf(pHlp, " Suppress multicast: ....... %s\n", pThis->fNoMulticast ? "true" : "false"); 938 pHlp->pfnPrintf(pHlp, " Promiscuous: .............. %s\n", pThis->fPromiscuous ? "true" : "false"); 939 pHlp->pfnPrintf(pHlp, "\n"); 940 pHlp->pfnPrintf(pHlp, " Default Rx MAC filter: .... %RTmac\n", pThis->rxFilterMacDefault); 941 pHlp->pfnPrintf(pHlp, "\n"); 942 943 pHlp->pfnPrintf(pHlp, " Unicast filter MACs:\n"); 944 945 if (!pThis->cUnicastFilterMacs) 946 pHlp->pfnPrintf(pHlp, " <none>\n"); 947 948 for (uint32_t i = 0; i < pThis->cUnicastFilterMacs; i++) 949 pHlp->pfnPrintf(pHlp, " %RTmac\n", &pThis->aMacUnicastFilter[i]); 950 951 pHlp->pfnPrintf(pHlp, "\n Multicast filter MACs:\n"); 952 953 if (!pThis->cMulticastFilterMacs) 954 pHlp->pfnPrintf(pHlp, " <none>\n"); 955 956 for (uint32_t i = 0; i < pThis->cMulticastFilterMacs; i++) 957 pHlp->pfnPrintf(pHlp, " %RTmac\n", &pThis->aMacMulticastFilter[i]); 958 959 pHlp->pfnPrintf(pHlp, "\n\n"); 960 pHlp->pfnPrintf(pHlp, " Leaf starved: ............. %s\n", pThis->fLeafWantsEmptyRxBufs ? "true" : "false"); 961 pHlp->pfnPrintf(pHlp, "\n"); 962 963 } 964 pHlp->pfnPrintf(pHlp, "\n"); 965 virtioCoreR3Info(pDevIns, pHlp, pszArgs); 966 pHlp->pfnPrintf(pHlp, "\n"); 967 } 968 723 969 /* 724 970 * Checks whether negotiated features have required flag combinations. … … 802 1048 uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIONET_CONFIG_T, member); \ 803 1049 if (fWrite) \ 804 LogFunc(("%s Guest attempted to write readonly virtio_pci_common_cfg.%s\n", INSTANCE(pThis), #member)); \1050 LogFunc(("%s Guest attempted to write readonly virtio_pci_common_cfg.%s\n", pThis->szInst, #member)); \ 805 1051 else \ 806 1052 { \ … … 829 1075 else 830 1076 { 831 LogFunc(("%s Bad access by guest to virtio_net_config: off=%u (%#x), cb=%u\n", INSTANCE(pThis), offConfig, offConfig, cb));1077 LogFunc(("%s Bad access by guest to virtio_net_config: off=%u (%#x), cb=%u\n", pThis->szInst, offConfig, offConfig, cb)); 832 1078 return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00; 833 1079 } … … 847 1093 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 848 1094 849 LogFunc(("%s uOffset: %d, cb: %d\n", INSTANCE(pThis), uOffset, cb));1095 LogFunc(("%s uOffset: %d, cb: %d\n", pThis->szInst, uOffset, cb)); 850 1096 RT_NOREF(pThis); 851 1097 return virtioNetR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIONET), uOffset, pv, cb, false /*fRead*/); … … 859 1105 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 860 1106 861 Log10Func(("%s uOffset: %d, cb: %d: %.*Rhxs\n", INSTANCE(pThis), uOffset, cb, RT_MAX(cb, 8) , pv));1107 Log10Func(("%s uOffset: %d, cb: %d: %.*Rhxs\n", pThis->szInst, uOffset, cb, RT_MAX(cb, 8) , pv)); 862 1108 RT_NOREF(pThis); 863 1109 return virtioNetR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIONET), uOffset, (void *)pv, cb, true /*fWrite*/); 864 }865 866 867 /*********************************************************************************************************************************868 * Misc *869 *********************************************************************************************************************************/870 871 /**872 * @callback_method_impl{FNDBGFHANDLERDEV, virtio-net debugger info callback.}873 */874 static DECLCALLBACK(void) virtioNetR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)875 {876 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);877 878 /* Parse arguments. */879 RT_NOREF2(pThis, pszArgs); //bool fVerbose = pszArgs && strstr(pszArgs, "verbose") != NULL;880 881 /* Show basic information. */882 pHlp->pfnPrintf(pHlp, "%s#%d: virtio-scsci ",883 pDevIns->pReg->szName,884 pDevIns->iInstance);885 1110 } 886 1111 … … 900 1125 901 1126 RT_NOREF(pThisCC); 902 Log7Func(("%s LOAD EXEC!!\n", INSTANCE(pThis)));1127 Log7Func(("%s LOAD EXEC!!\n", pThis->szInst)); 903 1128 904 1129 AssertReturn(uPass == SSM_PASS_FINAL, VERR_SSM_UNEXPECTED_PASS); … … 914 1139 915 1140 for (int idxQueue = 0; idxQueue < pThis->cVirtQueues; idxQueue++) 916 pHlp->pfnSSMGetBool(pSSM, &pThis->a fQueueAttached[idxQueue]);1141 pHlp->pfnSSMGetBool(pSSM, &pThis->aQueues[idxQueue].fAttachedToVirtioCore); 917 1142 918 1143 int rc; … … 930 1155 && (uPass == 0 || !PDMDevHlpVMTeleportedAndNotFullyResumedYet(pDevIns))) 931 1156 LogRel(("%s: The mac address differs: config=%RTmac saved=%RTmac\n", 932 INSTANCE(pThis), &pThis->macConfigured, &macConfigured));1157 pThis->szInst, &pThis->macConfigured, &macConfigured)); 933 1158 #endif 934 1159 … … 973 1198 for (int idxWorker = 0; idxWorker < pThis->cWorkers; idxWorker++) 974 1199 { 975 uint16_t idxQueue = pThisCC->aWorkers[idxWorker].idxQueue; 976 if (pThis->afQueueAttached[idxQueue]) 1200 PVIRTIONETWORKER pWorker = &pThis->aWorkers[idxWorker]; 1201 PVIRTIONETQUEUE pQueue = pWorker->pQueue; 1202 if (pQueue->fAttachedToVirtioCore) 977 1203 { 978 Log7Func(("%s Waking %s worker.\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));979 rc = PDMDevHlpSUPSemEventSignal(pDevIns, p This->aWorkers[idxWorker].hEvtProcess);1204 Log7Func(("%s Waking %s worker.\n", pThis->szInst, pQueue->szName)); 1205 rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess); 980 1206 AssertRCReturn(rc, rc); 981 1207 } … … 994 1220 995 1221 RT_NOREF(pThisCC); 996 Log7Func(("%s SAVE EXEC!!\n", INSTANCE(pThis)));1222 Log7Func(("%s SAVE EXEC!!\n", pThis->szInst)); 997 1223 998 1224 pHlp->pfnSSMPutU64( pSSM, pThis->fNegotiatedFeatures); … … 1002 1228 1003 1229 for (int idxQueue = 0; idxQueue < pThis->cVirtQueues; idxQueue++) 1004 pHlp->pfnSSMPutBool(pSSM, pThis->a fQueueAttached[idxQueue]);1230 pHlp->pfnSSMPutBool(pSSM, pThis->aQueues[idxQueue].fAttachedToVirtioCore); 1005 1231 1006 1232 /* Save config area */ … … 1053 1279 1054 1280 Log7Func(("%s Device I/O activity quiesced: %s\n", 1055 INSTANCE(pThis), virtioCoreGetStateChangeText(pThisCC->enmQuiescingFor)));1281 pThis->szInst, virtioCoreGetStateChangeText(pThisCC->enmQuiescingFor))); 1056 1282 1057 1283 virtioCoreR3VmStateChanged(&pThis->Virtio, pThisCC->enmQuiescingFor); … … 1086 1312 1087 1313 /* If already quiesced invoke async callback. */ 1088 if (!ASMAtomicReadBool(&pThis->fLeafWants RxBuffers))1314 if (!ASMAtomicReadBool(&pThis->fLeafWantsEmptyRxBufs)) 1089 1315 PDMDevHlpAsyncNotificationCompleted(pDevIns); 1090 1316 … … 1098 1324 { 1099 1325 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 1100 Log7Func(("%s\n", INSTANCE(pThis)));1326 Log7Func(("%s\n", pThis->szInst)); 1101 1327 pThis->fResetting = true; 1102 1328 virtioNetR3QuiesceDevice(pDevIns, kvirtIoVmStateChangedReset); … … 1111 1337 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 1112 1338 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 1113 Log7Func(("%s\n", INSTANCE(pThis)));1339 Log7Func(("%s\n", pThis->szInst)); 1114 1340 1115 1341 RT_NOREF2(pThis, pThisCC); … … 1125 1351 { 1126 1352 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 1127 Log7Func(("%s\n", INSTANCE(pThis)));1353 Log7Func(("%s\n", pThis->szInst)); 1128 1354 RT_NOREF(pThis); 1129 1355 virtioNetR3SuspendOrPowerOff(pDevIns, kvirtIoVmStateChangedPowerOff); … … 1136 1362 { 1137 1363 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 1138 Log7Func(("%s \n", INSTANCE(pThis)));1364 Log7Func(("%s \n", pThis->szInst)); 1139 1365 RT_NOREF(pThis); 1140 1366 virtioNetR3SuspendOrPowerOff(pDevIns, kvirtIoVmStateChangedSuspend); … … 1213 1439 void virtioNetR3SetWriteLed(PVIRTIONETR3 pThisR3, bool fOn) 1214 1440 { 1215 Log10Func(("%s\n", fOn ? "on" : "off"));1216 1441 if (fOn) 1217 1442 pThisR3->led.Asserted.s.fWriting = pThisR3->led.Actual.s.fWriting = 1; 1218 1443 else 1219 1444 pThisR3->led.Actual.s.fWriting = fOn; 1445 } 1446 1447 /* 1448 * Returns true if VirtIO core and device are in a running and operational state 1449 */ 1450 DECLINLINE(bool) virtioNetIsOperational(PVIRTIONET pThis, PPDMDEVINS pDevIns) 1451 { 1452 if (RT_LIKELY(pThis->fVirtioReady) && RT_LIKELY(!pThis->fQuiescing)) 1453 { 1454 VMSTATE enmVMState = PDMDevHlpVMState(pDevIns); 1455 if (RT_LIKELY(enmVMState == VMSTATE_RUNNING || enmVMState == VMSTATE_RUNNING_LS)) 1456 return true; 1457 } 1458 return false; 1220 1459 } 1221 1460 … … 1231 1470 * @thread RX 1232 1471 */ 1233 static int virtioNetR3IsRxQueuePrimed(PPDMDEVINS pDevIns, PVIRTIONET pThis, uint16_t idxRxQueue) 1234 { 1235 #define LOGPARAMS INSTANCE(pThis), VIRTQNAME(idxRxQueue) 1236 1237 if (!pThis->fVirtioReady) 1238 { 1239 Log8Func(("%s %s VirtIO not ready (rc = VERR_NET_NO_BUFFER_SPACE)\n", LOGPARAMS)); 1240 } 1241 else if (!virtioCoreIsQueueEnabled(&pThis->Virtio, idxRxQueue)) 1242 { 1243 Log8Func(("%s %s queue not enabled (rc = VERR_NET_NO_BUFFER_SPACE)\n", LOGPARAMS)); 1244 } 1245 else if (virtioCoreQueueIsEmpty(pDevIns, &pThis->Virtio, idxRxQueue)) 1246 { 1247 Log8Func(("%s %s queue is empty (rc = VERR_NET_NO_BUFFER_SPACE)\n", LOGPARAMS)); 1248 virtioCoreQueueSetNotify(&pThis->Virtio, idxRxQueue, true); 1249 } 1472 static int virtioNetR3CheckRxBufsAvail(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETQUEUE pRxQueue) 1473 { 1474 int rc = VERR_INVALID_STATE; 1475 1476 if (!virtioNetIsOperational(pThis, pDevIns)) 1477 Log8Func(("%s No Rx bufs available. (VirtIO core not ready)\n", pThis->szInst)); 1478 1479 else if (!virtioCoreIsQueueEnabled(&pThis->Virtio, pRxQueue->idx)) 1480 Log8Func(("%s No Rx bufs available. (%s not enabled)\n", pThis->szInst, pRxQueue->szName)); 1481 1482 else if (IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, pRxQueue->idx)) 1483 Log8Func(("%s No Rx bufs available. (%s empty)\n", pThis->szInst, pRxQueue->szName)); 1484 1250 1485 else 1251 1486 { 1252 Log8Func(("%s %s ready with available buffers\n", LOGPARAMS)); 1253 virtioCoreQueueSetNotify(&pThis->Virtio, idxRxQueue, false); 1254 return VINF_SUCCESS; 1255 } 1256 return VERR_NET_NO_BUFFER_SPACE; 1257 } 1258 1259 1260 static bool virtioNetR3AreRxBufsAvail(PPDMDEVINS pDevIns, PVIRTIONET pThis) 1261 { 1262 /** @todo If we ever start using more than one Rx/Tx queue pair, is a random queue 1263 selection algorithm feasible or even necessary to prevent starvation? */ 1487 Log8Func(("%s Empty guest buffers available in %s\n", pThis->szInst,pRxQueue->szName)); 1488 rc = VINF_SUCCESS; 1489 } 1490 virtioCoreQueueNotifyEnable(&pThis->Virtio, pRxQueue->idx, rc == VERR_INVALID_STATE /* fEnable */); 1491 return rc; 1492 } 1493 1494 static bool virtioNetR3RxBufsAvail(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETQUEUE *pRxQueue) 1495 { 1264 1496 for (int idxQueuePair = 0; idxQueuePair < pThis->cVirtqPairs; idxQueuePair++) 1265 if (RT_SUCCESS(virtioNetR3IsRxQueuePrimed(pDevIns, pThis, RXQIDX(idxQueuePair)))) 1497 { 1498 PVIRTIONETQUEUE pThisRxQueue = &pThis->aQueues[RXQIDX(idxQueuePair)]; 1499 if (RT_SUCCESS(virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pThisRxQueue))) 1500 { 1501 if (pRxQueue) 1502 *pRxQueue = pThisRxQueue; 1266 1503 return true; 1504 } 1505 } 1267 1506 return false; 1268 }1269 /*1270 * Returns true if VirtIO core and device are in a running and operational state1271 */1272 DECLINLINE(bool) virtioNetIsOperational(PVIRTIONET pThis, PPDMDEVINS pDevIns)1273 {1274 if (!pThis->fVirtioReady)1275 return false;1276 1277 if (pThis->fQuiescing)1278 return false;1279 1280 VMSTATE enmVMState = PDMDevHlpVMState(pDevIns);1281 if (!RT_LIKELY(enmVMState == VMSTATE_RUNNING || enmVMState == VMSTATE_RUNNING_LS))1282 return false;1283 1284 return true;1285 1507 } 1286 1508 … … 1294 1516 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 1295 1517 1296 if (virtioNetR3 AreRxBufsAvail(pDevIns, pThis))1297 { 1298 Log10Func(("%s Rx bufs now available, releasing waiter...\n", INSTANCE(pThis)));1299 1518 if (virtioNetR3RxBufsAvail(pDevIns, pThis, NULL /* pRxQueue */)) 1519 { 1520 Log10Func(("%s Rx bufs now available, releasing waiter...\n", pThis->szInst)); 1521 return VINF_SUCCESS; 1300 1522 } 1301 1523 if (!timeoutMs) 1302 1524 return VERR_NET_NO_BUFFER_SPACE; 1303 1525 1304 LogF lowFunc(("%s timeoutMs=%u\n", INSTANCE(pThis), timeoutMs));1305 1306 ASMAtomicXchgBool(&pThis->fLeafWants RxBuffers, true);1526 LogFunc(("%s %s\n", pThis->szInst, timeoutMs == RT_INDEFINITE_WAIT ? "<indefinite wait>" : "")); 1527 1528 ASMAtomicXchgBool(&pThis->fLeafWantsEmptyRxBufs, true); 1307 1529 STAM_PROFILE_START(&pThis->StatRxOverflow, a); 1308 1530 1309 1531 do { 1310 if (virtioNetR3 AreRxBufsAvail(pDevIns, pThis))1532 if (virtioNetR3RxBufsAvail(pDevIns, pThis, NULL /* pRxQueue */)) 1311 1533 { 1312 Log10Func(("%s Rx bufs now available, releasing waiter...\n", INSTANCE(pThis)));1313 1534 Log10Func(("%s Rx bufs now available, releasing waiter...\n", pThis->szInst)); 1535 return VINF_SUCCESS; 1314 1536 } 1315 Log9Func(("%s Starved for guest Rx bufs, waiting %u ms ...\n", 1316 INSTANCE(pThis), timeoutMs)); 1537 Log9Func(("%s Starved for empty guest Rx bufs. Waiting...\n", pThis->szInst)); 1317 1538 1318 1539 int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEventRxDescAvail, timeoutMs); 1319 1540 1320 1541 if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED) 1542 { 1543 LogFunc(("Waken due to %s\n", rc == VERR_TIMEOUT ? "timeout" : "interrupted")); 1321 1544 continue; 1322 1323 if (RT_FAILURE(rc)) 1545 } 1546 if (RT_FAILURE(rc)) { 1547 LogFunc(("Waken due to failure %Rrc\n", rc)); 1324 1548 RTThreadSleep(1); 1325 1549 } 1550 LogFunc(("\n\n\n********** WAKEN!!!!! ********\n\n\n")); 1326 1551 } while (virtioNetIsOperational(pThis, pDevIns)); 1327 1552 1328 1553 STAM_PROFILE_STOP(&pThis->StatRxOverflow, a); 1329 ASMAtomicXchgBool(&pThis->fLeafWants RxBuffers, false);1330 1331 Log7Func(("%s Wait for Rx buffers available was interrupted\n", INSTANCE(pThis)));1554 ASMAtomicXchgBool(&pThis->fLeafWantsEmptyRxBufs, false); 1555 1556 Log7Func(("%s Wait for Rx buffers available was interrupted\n", pThis->szInst)); 1332 1557 return VERR_INTERRUPTED; 1333 1558 } … … 1435 1660 1436 1661 LogFunc(("%s node(%RTmac %s%s), pkt(%RTmac %s)", 1437 INSTANCE(pThis), pThis->virtioNetConfig.uMacAddress.au8,1662 pThis->szInst, pThis->virtioNetConfig.uMacAddress.au8, 1438 1663 pThis->fPromiscuous ? "promiscuous" : "", 1439 1664 pThis->fAllMulticast ? " all-multicast" : "", … … 1451 1676 && !ASMBitTest(pThis->aVlanFilter, RT_BE2H_U16(uPtr[7]) & 0xFFF)) 1452 1677 { 1453 Log11Func(("\n%s not our VLAN, returning false\n", INSTANCE(pThis)));1678 Log11Func(("\n%s not our VLAN, returning false\n", pThis->szInst)); 1454 1679 return false; 1455 1680 } … … 1505 1730 VIRTIONET_PKT_HDR_T *rxPktHdr, uint16_t cSegsAllocated, 1506 1731 PRTSGBUF pVirtSegBufToGuest, PRTSGSEG paVirtSegsToGuest, 1507 uint16_t idxRxQueue)1732 PVIRTIONETQUEUE pRxQueue) 1508 1733 { 1509 1734 uint8_t fAddPktHdr = true; 1510 RTGCPHYS gcPhysPktHdrNumBuffers = 0;1735 RTGCPHYS GCPhysPktHdrNumBuffers = 0; 1511 1736 uint16_t cDescs; 1512 1737 uint64_t uOffset; … … 1515 1740 PVIRTIO_DESC_CHAIN_T pDescChain = NULL; 1516 1741 1517 int rc = virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, RXQIDX(idxRxQueue), &pDescChain, true);1742 int rc = virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, pRxQueue->idx, &pDescChain, true); 1518 1743 AssertMsgReturn(rc == VINF_SUCCESS || rc == VERR_NOT_AVAILABLE, ("%Rrc\n", rc), rc); 1519 1744 … … 1526 1751 /* Length of first seg of guest Rx buf should never be less than sizeof(virtio_net_pkt_hdr). 1527 1752 * Otherwise code has to become more complicated, e.g. locate & cache seg idx & offset of 1528 * virtio_net_header.num_buffers, to defer updating (in gcPhys). Re-visit if needed */1753 * virtio_net_header.num_buffers, to defer updating (in GCPhys). Re-visit if needed */ 1529 1754 1530 1755 AssertMsgReturnStmt(pDescChain->pSgPhysReturn->paSegs[0].cbSeg >= sizeof(VIRTIONET_PKT_HDR_T), … … 1549 1774 memcpy(paVirtSegsToGuest[0].pvSeg, rxPktHdr, cbHdr); 1550 1775 1551 /* Calculate & cache addr of field to update after final value is known, in gcPhys mem */1552 gcPhysPktHdrNumBuffers = pDescChain->pSgPhysReturn->paSegs[0].gcPhys1776 /* Calculate & cache addr of field to update after final value is known, in GCPhys mem */ 1777 GCPhysPktHdrNumBuffers = pDescChain->pSgPhysReturn->paSegs[0].GCPhys 1553 1778 + RT_UOFFSETOF(VIRTIONET_PKT_HDR_T, uNumBuffers); 1554 1779 fAddPktHdr = false; … … 1576 1801 Log7Func(("Send Rx pkt to guest...\n")); 1577 1802 STAM_PROFILE_START(&pThis->StatReceiveStore, a); 1578 virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, idxRxQueue,1579 pVirtSegBufToGuest, pDescChain, true );1803 virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, pRxQueue->idx, 1804 pVirtSegBufToGuest, pDescChain, true /* fFence */); 1580 1805 STAM_PROFILE_STOP(&pThis->StatReceiveStore, a); 1581 1806 … … 1589 1814 if (uOffset < cb) 1590 1815 { 1591 LogFunc(("%s Packet did not fit into RX queue (packet size=%u)!\n", INSTANCE(pThis), cb));1816 LogFunc(("%s Packet did not fit into RX queue (packet size=%u)!\n", pThis->szInst, cb)); 1592 1817 return VERR_TOO_MUCH_DATA; 1593 1818 } … … 1595 1820 /* Fix-up pkthdr (in guest phys. memory) with number buffers (descriptors) processed */ 1596 1821 1597 int rc = PDMDevHlpPCIPhysWrite(pDevIns, gcPhysPktHdrNumBuffers, &cDescs, sizeof(cDescs));1822 int rc = PDMDevHlpPCIPhysWrite(pDevIns, GCPhysPktHdrNumBuffers, &cDescs, sizeof(cDescs)); 1598 1823 AssertMsgRCReturn(rc, 1599 1824 ("Failure updating descriptor count in pkt hdr in guest physical memory\n"), 1600 1825 rc); 1601 1826 1602 virtioCoreQueueSync(pDevIns, &pThis->Virtio, RXQIDX(idxRxQueue));1827 virtioCoreQueueSync(pDevIns, &pThis->Virtio, pRxQueue->idx); 1603 1828 1604 1829 return VINF_SUCCESS; … … 1622 1847 */ 1623 1848 static int virtioNetR3HandleRxPacket(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 1624 const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso, uint16_t idxRxQueue)1849 const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso, PVIRTIONETQUEUE pRxQueue) 1625 1850 { 1626 1851 RT_NOREF(pThisCC); 1627 1852 1628 LogFunc(("%s (%RTmac) pGso %s\n", INSTANCE(pThis), pvBuf, pGso ? "present" : "not present"));1853 LogFunc(("%s (%RTmac) pGso %s\n", pThis->szInst, pvBuf, pGso ? "present" : "not present")); 1629 1854 VIRTIONET_PKT_HDR_T rxPktHdr = { 0 }; 1630 1855 … … 1632 1857 { 1633 1858 Log2Func(("%s gso type=%x cbPktHdrsTotal=%u cbPktHdrsSeg=%u mss=%u off1=0x%x off2=0x%x\n", 1634 INSTANCE(pThis), pGso->u8Type, pGso->cbHdrsTotal,1859 pThis->szInst, pGso->u8Type, pGso->cbHdrsTotal, 1635 1860 pGso->cbHdrsSeg, pGso->cbMaxSeg, pGso->offHdr1, pGso->offHdr2)); 1636 1861 … … 1673 1898 1674 1899 int rc = virtioNetR3CopyRxPktToGuest(pDevIns, pThis, pvBuf, cb, &rxPktHdr, cSegsAllocated, 1675 pVirtSegBufToGuest, paVirtSegsToGuest, idxRxQueue);1900 pVirtSegBufToGuest, paVirtSegsToGuest, pRxQueue); 1676 1901 1677 1902 RTMemFree(paVirtSegsToGuest); … … 1691 1916 PPDMDEVINS pDevIns = pThisCC->pDevIns; 1692 1917 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 1693 1918 LogFunc(("\n")); 1694 1919 if (!pThis->fVirtioReady) 1695 1920 { … … 1725 1950 if (!uFeatures) 1726 1951 { 1727 Log 2Func(("%s GSO type (0x%x) not supported\n", INSTANCE(pThis), pGso->u8Type));1952 LogFunc(("%s GSO type (0x%x) not supported\n", pThis->szInst, pGso->u8Type)); 1728 1953 return VERR_NOT_SUPPORTED; 1729 1954 } 1730 1955 } 1731 1956 1732 Log10Func(("%s pvBuf=%p cb=%3u pGso=%p ... ", INSTANCE(pThis), pvBuf, cb, pGso));1957 Log10Func(("%s pvBuf=%p cb=%3u pGso=%p ...\n", pThis->szInst, pvBuf, cb, pGso)); 1733 1958 1734 1959 /** @todo If we ever start using more than one Rx/Tx queue pair, is a random queue … … 1737 1962 for (int idxQueuePair = 0; idxQueuePair < pThis->cVirtqPairs; idxQueuePair++) 1738 1963 { 1739 if (RT_SUCCESS(!virtioNetR3IsRxQueuePrimed(pDevIns, pThis, RXQIDX(idxQueuePair)))) 1964 1965 PVIRTIONETQUEUE pRxQueue = &pThis->aQueues[RXQIDX(idxQueuePair)]; 1966 if (RT_SUCCESS(!virtioNetR3CheckRxBufsAvail(pDevIns, pThis, pRxQueue))) 1740 1967 { 1741 1968 /* Drop packets if VM is not running or cable is disconnected. */ … … 1749 1976 if (virtioNetR3AddressFilter(pThis, pvBuf, cb)) 1750 1977 { 1751 rc = virtioNetR3HandleRxPacket(pDevIns, pThis, pThisCC, pvBuf, cb, pGso, RXQIDX(idxQueuePair));1978 rc = virtioNetR3HandleRxPacket(pDevIns, pThis, pThisCC, pvBuf, cb, pGso, pRxQueue); 1752 1979 STAM_REL_COUNTER_ADD(&pThis->StatReceiveBytes, cb); 1753 1980 } … … 1784 2011 } 1785 2012 LogFunc(("%s Pulled %d/%d bytes from desc chain (%d bytes left)\n", 1786 INSTANCE(pThis), cb - cbLim, cb, pDescChain->cbPhysSend));2013 pThis->szInst, cb - cbLim, cb, pDescChain->cbPhysSend)); 1787 2014 RT_NOREF(pThis); 1788 2015 } … … 1792 2019 { 1793 2020 1794 #define LOG_VIRTIONET_FLAG(fld) LogFunc(("%s Setting %s=%d\n", INSTANCE(pThis), #fld, pThis->fld))1795 1796 LogFunc(("%s Processing CTRL Rx command\n", INSTANCE(pThis)));2021 #define LOG_VIRTIONET_FLAG(fld) LogFunc(("%s Setting %s=%d\n", pThis->szInst, #fld, pThis->fld)) 2022 2023 LogFunc(("%s Processing CTRL Rx command\n", pThis->szInst)); 1797 2024 RT_NOREF(pThis); 1798 2025 switch(pCtrlPktHdr->uCmd) … … 1866 2093 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTIO_DESC_CHAIN_T pDescChain) 1867 2094 { 1868 LogFunc(("%s Processing CTRL MAC command\n", INSTANCE(pThis)));2095 LogFunc(("%s Processing CTRL MAC command\n", pThis->szInst)); 1869 2096 1870 2097 RT_NOREF(pThisCC); … … 1898 2125 virtioNetR3PullChain(pDevIns, pThis, pDescChain, &cMacs, sizeof(cMacs)); 1899 2126 cbRemaining -= sizeof(cMacs); 1900 Log7Func(("%s Guest provided %d unicast MAC Table entries\n", INSTANCE(pThis), cMacs));2127 Log7Func(("%s Guest provided %d unicast MAC Table entries\n", pThis->szInst, cMacs)); 1901 2128 if (cMacs) 1902 2129 { … … 1912 2139 virtioNetR3PullChain(pDevIns, pThis, pDescChain, &cMacs, sizeof(cMacs)); 1913 2140 cbRemaining -= sizeof(cMacs); 1914 Log10Func(("%s Guest provided %d multicast MAC Table entries\n", INSTANCE(pThis), cMacs));2141 Log10Func(("%s Guest provided %d multicast MAC Table entries\n", pThis->szInst, cMacs)); 1915 2142 if (cMacs) 1916 2143 { … … 1923 2150 1924 2151 #ifdef LOG_ENABLED 1925 LogFunc(("%s unicast MACs:\n", INSTANCE(pThis)));2152 LogFunc(("%s unicast MACs:\n", pThis->szInst)); 1926 2153 for(unsigned i = 0; i < cMacs; i++) 1927 2154 LogFunc((" %RTmac\n", &pThis->aMacUnicastFilter[i])); 1928 2155 1929 LogFunc(("%s multicast MACs:\n", INSTANCE(pThis)));2156 LogFunc(("%s multicast MACs:\n", pThis->szInst)); 1930 2157 for(unsigned i = 0; i < cMacs; i++) 1931 2158 LogFunc((" %RTmac\n", &pThis->aMacMulticastFilter[i])); … … 1939 2166 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTIO_DESC_CHAIN_T pDescChain) 1940 2167 { 1941 LogFunc(("%s Processing CTRL VLAN command\n", INSTANCE(pThis)));2168 LogFunc(("%s Processing CTRL VLAN command\n", pThis->szInst)); 1942 2169 1943 2170 RT_NOREF(pThisCC); … … 1949 2176 virtioNetR3PullChain(pDevIns, pThis, pDescChain, &uVlanId, sizeof(uVlanId)); 1950 2177 AssertMsgReturn(uVlanId > VIRTIONET_MAX_VLAN_ID, 1951 ("%s VLAN ID out of range (VLAN ID=%u)\n", INSTANCE(pThis), uVlanId), VIRTIONET_ERROR);1952 LogFunc(("%s uCommand=%u VLAN ID=%u\n", INSTANCE(pThis), pCtrlPktHdr->uCmd, uVlanId));2178 ("%s VLAN ID out of range (VLAN ID=%u)\n", pThis->szInst, uVlanId), VIRTIONET_ERROR); 2179 LogFunc(("%s uCommand=%u VLAN ID=%u\n", pThis->szInst, pCtrlPktHdr->uCmd, uVlanId)); 1953 2180 switch (pCtrlPktHdr->uCmd) 1954 2181 { … … 1968 2195 PVIRTIO_DESC_CHAIN_T pDescChain) 1969 2196 { 1970 LogFunc(("%s Received CTRL packet from guest\n", INSTANCE(pThis)));2197 LogFunc(("%s Received CTRL packet from guest\n", pThis->szInst)); 1971 2198 1972 2199 if (pDescChain->cbPhysSend < 2) 1973 2200 { 1974 LogFunc(("%s CTRL packet from guest driver incomplete. Skipping ctrl cmd\n", INSTANCE(pThis)));2201 LogFunc(("%s CTRL packet from guest driver incomplete. Skipping ctrl cmd\n", pThis->szInst)); 1975 2202 return; 1976 2203 } 1977 2204 else if (pDescChain->cbPhysReturn < sizeof(VIRTIONET_CTRL_HDR_T_ACK)) 1978 2205 { 1979 LogFunc(("%s Guest driver didn't allocate memory to receive ctrl pkt ACK. Skipping ctrl cmd\n", INSTANCE(pThis)));2206 LogFunc(("%s Guest driver didn't allocate memory to receive ctrl pkt ACK. Skipping ctrl cmd\n", pThis->szInst)); 1980 2207 return; 1981 2208 } … … 1994 2221 RT_MIN(pDescChain->cbPhysSend, sizeof(VIRTIONET_CTRL_HDR_T))); 1995 2222 1996 Log7Func(("%s CTRL COMMAND: class=%d command=%d\n", INSTANCE(pThis), pCtrlPktHdr->uClass, pCtrlPktHdr->uCmd));2223 Log7Func(("%s CTRL COMMAND: class=%d command=%d\n", pThis->szInst, pCtrlPktHdr->uClass, pCtrlPktHdr->uCmd)); 1997 2224 1998 2225 uint8_t uAck; … … 2013 2240 { 2014 2241 LogFunc(("%s Ignoring CTRL class VIRTIONET_CTRL_ANNOUNCE.\n" 2015 "VIRTIO_F_STATUS or VIRTIO_F_GUEST_ANNOUNCE feature not enabled\n", INSTANCE(pThis)));2242 "VIRTIO_F_STATUS or VIRTIO_F_GUEST_ANNOUNCE feature not enabled\n", pThis->szInst)); 2016 2243 break; 2017 2244 } 2018 2245 if (pCtrlPktHdr->uCmd != VIRTIONET_CTRL_ANNOUNCE_ACK) 2019 2246 { 2020 LogFunc(("%s Ignoring CTRL class VIRTIONET_CTRL_ANNOUNCE. Unrecognized uCmd\n", INSTANCE(pThis)));2247 LogFunc(("%s Ignoring CTRL class VIRTIONET_CTRL_ANNOUNCE. Unrecognized uCmd\n", pThis->szInst)); 2021 2248 break; 2022 2249 } 2023 2250 pThis->virtioNetConfig.uStatus &= ~VIRTIONET_F_ANNOUNCE; 2024 Log7Func(("%s Clearing VIRTIONET_F_ANNOUNCE in config status\n", INSTANCE(pThis)));2251 Log7Func(("%s Clearing VIRTIONET_F_ANNOUNCE in config status\n", pThis->szInst)); 2025 2252 break; 2026 2253 … … 2055 2282 RTSgBufInit(pReturnSegBuf, paReturnSegs, cSegs); 2056 2283 2057 virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, CTRLQIDX, pReturnSegBuf, pDescChain, true );2284 virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, CTRLQIDX, pReturnSegBuf, pDescChain, true /* fFence */); 2058 2285 virtioCoreQueueSync(pDevIns, &pThis->Virtio, CTRLQIDX); 2059 2286 … … 2065 2292 2066 2293 LogFunc(("%s Finished processing CTRL command with status %s\n", 2067 INSTANCE(pThis), uAck == VIRTIONET_OK ? "VIRTIONET_OK" : "VIRTIONET_ERROR"));2294 pThis->szInst, uAck == VIRTIONET_OK ? "VIRTIONET_OK" : "VIRTIONET_ERROR")); 2068 2295 } 2069 2296 … … 2074 2301 return rc; 2075 2302 2076 Log (("virtio-net: header (flags=%x gso-type=%x len=%x gso-size=%x Chksum-start=%x Chksum-offset=%x) cbFrame=%d\n",2303 LogFunc(("pktHdr (flags=%x gso-type=%x len=%x gso-size=%x Chksum-start=%x Chksum-offset=%x) cbFrame=%d\n", 2077 2304 pPktHdr->uFlags, pPktHdr->uGsoType, pPktHdr->uHdrLen, 2078 2305 pPktHdr->uGsoSize, pPktHdr->uChksumStart, pPktHdr->uChksumOffset, cbFrame)); … … 2128 2355 { 2129 2356 Log4Func(("%s HdrLen before adjustment %d.\n", 2130 INSTANCE(pThis), pGso->cbHdrsTotal));2357 pThis->szInst, pGso->cbHdrsTotal)); 2131 2358 switch (pGso->u8Type) 2132 2359 { … … 2146 2373 ((PPDMNETWORKGSO)pSgBuf->pvUser)->cbHdrsSeg = pGso->cbHdrsSeg; 2147 2374 Log4Func(("%s adjusted HdrLen to %d.\n", 2148 INSTANCE(pThis), pGso->cbHdrsTotal));2375 pThis->szInst, pGso->cbHdrsTotal)); 2149 2376 } 2150 2377 Log2Func(("%s gso type=%x cbHdrsTotal=%u cbHdrsSeg=%u mss=%u off1=0x%x off2=0x%x\n", 2151 INSTANCE(pThis), pGso->u8Type, pGso->cbHdrsTotal, pGso->cbHdrsSeg,2378 pThis->szInst, pGso->u8Type, pGso->cbHdrsTotal, pGso->cbHdrsSeg, 2152 2379 pGso->cbMaxSeg, pGso->offHdr1, pGso->offHdr2)); 2153 2380 STAM_REL_COUNTER_INC(&pThis->StatTransmitGSO); … … 2163 2390 } 2164 2391 2165 return pThisCC->pDrv->pfnSendBuf(pThisCC->pDrv, pSgBuf, false);2392 return pThisCC->pDrv->pfnSendBuf(pThisCC->pDrv, pSgBuf, true /* fOnWorkerThread */); 2166 2393 } 2167 2394 2168 2395 static void virtioNetR3TransmitPendingPackets(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 2169 uint16_t idxTxQueue, bool fOnWorkerThread)2396 PVIRTIONETQUEUE pTxQueue, bool fOnWorkerThread) 2170 2397 { 2171 2398 … … 2183 2410 { 2184 2411 LogFunc(("%s Ignoring Tx requests. VirtIO not ready (status=0x%x).\n", 2185 INSTANCE(pThis), pThis->virtioNetConfig.uStatus));2412 pThis->szInst, pThis->virtioNetConfig.uStatus)); 2186 2413 return; 2187 2414 } … … 2189 2416 if (!pThis->fCableConnected) 2190 2417 { 2191 Log(("%s Ignoring transmit requests while cable is disconnected.\n", INSTANCE(pThis)));2418 Log(("%s Ignoring transmit requests while cable is disconnected.\n", pThis->szInst)); 2192 2419 return; 2193 2420 } … … 2205 2432 } 2206 2433 2207 int cPkts = virtioCore R3QueuePendingCount(pVirtio->pDevInsR3, pVirtio, idxTxQueue);2434 int cPkts = virtioCoreQueueAvailCount(pVirtio->pDevInsR3, pVirtio, pTxQueue->idx); 2208 2435 if (!cPkts) 2209 2436 { 2210 LogFunc(("%s No packets to send found on %s\n", INSTANCE(pThis), VIRTQNAME(idxTxQueue)));2437 LogFunc(("%s No packets to send found on %s\n", pThis->szInst, pTxQueue->szName)); 2211 2438 2212 2439 if (pDrv) … … 2216 2443 return; 2217 2444 } 2218 LogFunc(("%s About to transmit %d pending packet s\n", INSTANCE(pThis), cPkts));2445 LogFunc(("%s About to transmit %d pending packet%c\n", pThis->szInst, cPkts, cPkts == 1 ? ' ' : 's')); 2219 2446 2220 2447 virtioNetR3SetWriteLed(pThisCC, true); … … 2222 2449 int rc; 2223 2450 PVIRTIO_DESC_CHAIN_T pDescChain = NULL; 2224 while ((rc = virtioCoreR3QueuePeek(pVirtio->pDevInsR3, pVirtio, idxTxQueue, &pDescChain)) == VINF_SUCCESS)2225 { 2226 Log10Func(("%s fetched descriptor chain from %s\n", INSTANCE(pThis), VIRTQNAME(idxTxQueue)));2451 while ((rc = virtioCoreR3QueuePeek(pVirtio->pDevInsR3, pVirtio, pTxQueue->idx, &pDescChain)) == VINF_SUCCESS) 2452 { 2453 Log10Func(("%s fetched descriptor chain from %s\n", pThis->szInst, pTxQueue->szName)); 2227 2454 2228 2455 PVIRTIOSGBUF pSgPhysSend = pDescChain->pSgPhysSend; … … 2239 2466 uSize += paSegsFromGuest[i].cbSeg; 2240 2467 2241 Log5Func(("%s complete frame is %u bytes.\n", INSTANCE(pThis), uSize));2468 Log5Func(("%s complete frame is %u bytes.\n", pThis->szInst, uSize)); 2242 2469 Assert(uSize <= VIRTIONET_MAX_FRAME_SIZE); 2243 2470 … … 2248 2475 if (pThisCC->pDrv) 2249 2476 { 2250 PDMNETWORKGSO Gso;2251 PPDMNETWORKGSO pGso = virtioNetR3SetupGsoCtx(&Gso, &PktHdr);2252 2477 uint64_t uOffset; 2478 2479 uSize -= sizeof(PktHdr); 2480 rc = virtioNetR3ReadHeader(pDevIns, paSegsFromGuest[0].GCPhys, &PktHdr, uSize); 2481 if (RT_FAILURE(rc)) 2482 return; 2483 virtioCoreSgBufAdvance(pSgPhysSend, sizeof(PktHdr)); 2484 2485 PDMNETWORKGSO Gso, *pGso = virtioNetR3SetupGsoCtx(&Gso, &PktHdr); 2253 2486 2254 2487 PPDMSCATTERGATHER pSgBufToPdmLeafDevice; … … 2258 2491 STAM_REL_COUNTER_INC(&pThis->StatTransmitPackets); 2259 2492 STAM_PROFILE_START(&pThis->StatTransmitSend, a); 2260 2261 uSize -= sizeof(PktHdr);2262 rc = virtioNetR3ReadHeader(pDevIns, paSegsFromGuest[0].gcPhys, &PktHdr, uSize);2263 if (RT_FAILURE(rc))2264 return;2265 virtioCoreSgBufAdvance(pSgPhysSend, sizeof(PktHdr));2266 2493 2267 2494 size_t cbCopied = 0; … … 2272 2499 { 2273 2500 PVIRTIOSGSEG paSeg = &pSgPhysSend->paSegs[pSgPhysSend->idxSeg]; 2274 uint64_t srcSgStart = (uint64_t)paSeg-> gcPhys;2501 uint64_t srcSgStart = (uint64_t)paSeg->GCPhys; 2275 2502 uint64_t srcSgLen = (uint64_t)paSeg->cbSeg; 2276 uint64_t srcSgCur = (uint64_t)pSgPhysSend-> gcPhysCur;2503 uint64_t srcSgCur = (uint64_t)pSgPhysSend->GCPhysCur; 2277 2504 cbCopied = RT_MIN((uint64_t)cbRemain, srcSgLen - (srcSgCur - srcSgStart)); 2278 2505 PDMDevHlpPCIPhysRead(pDevIns, 2279 (RTGCPHYS)pSgPhysSend-> gcPhysCur,2506 (RTGCPHYS)pSgPhysSend->GCPhysCur, 2280 2507 ((uint8_t *)pSgBufToPdmLeafDevice->aSegs[0].pvSeg) + uOffset, cbCopied); 2281 2508 virtioCoreSgBufAdvance(pSgPhysSend, cbCopied); … … 2291 2518 if (RT_FAILURE(rc)) 2292 2519 { 2293 LogFunc(("%s Failed to transmit frame, rc = %Rrc\n", INSTANCE(pThis), rc));2520 LogFunc(("%s Failed to transmit frame, rc = %Rrc\n", pThis->szInst, rc)); 2294 2521 STAM_PROFILE_STOP(&pThis->StatTransmitSend, a); 2295 2522 STAM_PROFILE_ADV_STOP(&pThis->StatTransmit, a); … … 2308 2535 2309 2536 /* Remove this descriptor chain from the available ring */ 2310 virtioCoreR3QueueSkip(pVirtio, idxTxQueue);2537 virtioCoreR3QueueSkip(pVirtio, pTxQueue->idx); 2311 2538 2312 2539 /* No data to return to guest, but call is needed put elem (e.g. desc chain) on used ring */ 2313 virtioCoreR3QueuePut(pVirtio->pDevInsR3, pVirtio, idxTxQueue, NULL, pDescChain, false);2540 virtioCoreR3QueuePut(pVirtio->pDevInsR3, pVirtio, pTxQueue->idx, NULL, pDescChain, true /* fFence */); 2314 2541 2315 2542 /* Update used ring idx and notify guest that we've transmitted the data it sent */ 2316 virtioCoreQueueSync(pVirtio->pDevInsR3, pVirtio, idxTxQueue);2543 virtioCoreQueueSync(pVirtio->pDevInsR3, pVirtio, pTxQueue->idx); 2317 2544 } 2318 2545 … … 2337 2564 PPDMDEVINS pDevIns = pThisCC->pDevIns; 2338 2565 PVIRTIONET pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVIRTIONET); 2339 2566 PVIRTIONETQUEUE pTxQueue = &pThis->aQueues[TXQIDX(0)]; 2340 2567 STAM_COUNTER_INC(&pThis->StatTransmitByNetwork); 2341 2568 2342 2569 /** @todo If we ever start using more than one Rx/Tx queue pair, is a random queue 2343 2570 selection algorithm feasible or even necessary */ 2344 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, TXQIDX(0), false /*fOnWorkerThread*/); 2345 } 2346 2347 /** 2348 * @callback_method_impl{FNPDMTHREADDEV} 2349 */ 2350 static DECLCALLBACK(int) virtioNetR3WorkerThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 2351 { 2352 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 2353 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 2354 uint16_t const idxWorker = (uint16_t)(uintptr_t)pThread->pvUser; 2355 PVIRTIONETWORKER pWorker = &pThis->aWorkers[idxWorker]; 2356 PVIRTIONETWORKERR3 pWorkerR3 = &pThisCC->aWorkers[idxWorker]; 2357 uint16_t const idxQueue = pWorkerR3->idxQueue; 2358 2359 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 2360 { 2361 return VINF_SUCCESS; 2362 } 2363 LogFunc(("%s worker thread started for %s\n", INSTANCE(pThis), VIRTQNAME(idxQueue))); 2364 virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, false); 2365 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 2366 { 2367 if (virtioCoreQueueIsEmpty(pDevIns, &pThis->Virtio, idxQueue)) 2368 { 2369 /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */ 2370 virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, true); 2371 ASMAtomicWriteBool(&pWorker->fSleeping, true); 2372 bool fNotificationSent = ASMAtomicXchgBool(&pWorker->fNotified, false); 2373 if (!fNotificationSent) 2374 { 2375 Log10Func(("%s %s worker sleeping...\n", INSTANCE(pThis), VIRTQNAME(idxQueue))); 2376 Assert(ASMAtomicReadBool(&pWorker->fSleeping)); 2377 int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pWorker->hEvtProcess, RT_INDEFINITE_WAIT); 2378 STAM_COUNTER_INC(&pThis->StatTransmitByThread); 2379 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc); 2380 if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING)) 2381 return VINF_SUCCESS; 2382 if (rc == VERR_INTERRUPTED) 2383 { 2384 virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, false); 2385 continue; 2386 } 2387 Log10Func(("%s %s worker woken\n", INSTANCE(pThis), VIRTQNAME(idxQueue))); 2388 ASMAtomicWriteBool(&pWorker->fNotified, false); 2389 } 2390 ASMAtomicWriteBool(&pWorker->fSleeping, false); 2391 virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, false); 2392 } 2393 2394 /* Dispatch to the handler for the queue this worker is set up to drive */ 2395 2396 if (!pThisCC->fQuiescing) 2397 { 2398 if (IS_CTRL_QUEUE(idxQueue)) 2399 { 2400 Log10Func(("%s fetching next descriptor chain from %s\n", INSTANCE(pThis), VIRTQNAME(idxQueue))); 2401 PVIRTIO_DESC_CHAIN_T pDescChain = NULL; 2402 int rc = virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, idxQueue, &pDescChain, true); 2403 if (rc == VERR_NOT_AVAILABLE) 2404 { 2405 Log10Func(("%s Nothing found in %s\n", INSTANCE(pThis), VIRTQNAME(idxQueue))); 2406 continue; 2407 } 2408 virtioNetR3Ctrl(pDevIns, pThis, pThisCC, pDescChain); 2409 virtioCoreR3DescChainRelease(&pThis->Virtio, pDescChain); 2410 } 2411 else if (IS_TX_QUEUE(idxQueue)) 2412 { 2413 Log10Func(("%s Notified of data to transmit\n", INSTANCE(pThis))); 2414 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, 2415 idxQueue, false /* fOnWorkerThread */); 2416 } 2417 2418 /* Rx queues aren't handled by our worker threads. Instead, the PDM network 2419 * leaf driver invokes PDMINETWORKDOWN.pfnWaitReceiveAvail() callback, 2420 * which waits until notified directly by virtioNetQueueNotified() 2421 * that guest IN buffers have been added to receive virt queue. 2422 */ 2423 } 2424 } 2425 return VINF_SUCCESS; 2426 } 2571 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pTxQueue, true /*fOnWorkerThread*/); 2572 } 2573 2427 2574 2428 2575 #ifdef USING_CRITICAL_SECTION … … 2431 2578 RT_NOREF(pDevIns, pThis, rcBusy); 2432 2579 /* Original DevVirtioNet uses CS in attach/detach/link-up timer/tx timer/transmit */ 2433 LogFunc(("%s CS unimplemented. What does the critical section protect in orig driver??", INSTANCE(pThis)));2580 LogFunc(("%s CS unimplemented. What does the critical section protect in orig driver??", pThis->szInst)); 2434 2581 return VINF_SUCCESS; 2435 2582 } … … 2438 2585 { 2439 2586 RT_NOREF(pDevIns, pThis); 2440 LogFunc(("%s CS unimplemented. What does the critical section protect in orig driver??", INSTANCE(pThis)));2587 LogFunc(("%s CS unimplemented. What does the critical section protect in orig driver??", pThis->szInst)); 2441 2588 } 2442 2589 #endif /* USING_CRITICAL_SECTION */ … … 2459 2606 LEAVE_CRITICAL_SECTION; 2460 2607 2461 LogFunc(("%s Link is up\n", INSTANCE(pThis)));2608 LogFunc(("%s Link is up\n", pThis->szInst)); 2462 2609 2463 2610 if (pThisCC->pDrv) … … 2488 2635 AssertRC(rc); 2489 2636 2490 LogFunc(("%s Link is down temporarily\n", INSTANCE(pThis))); 2491 } 2492 } 2493 2494 /** 2495 * @interface_method_impl{PDMINETWORKCONFIG,pfnGetLinkState} 2496 */ 2497 static DECLCALLBACK(PDMNETWORKLINKSTATE) virtioNetR3NetworkConfig_GetLinkState(PPDMINETWORKCONFIG pInterface) 2498 { 2499 PVIRTIONETCC pThisCC = RT_FROM_MEMBER(pInterface, VIRTIONETCC, INetworkConfig); 2500 PVIRTIONET pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVIRTIONET); 2501 2502 return IS_LINK_UP(pThis) ? PDMNETWORKLINKSTATE_UP : PDMNETWORKLINKSTATE_DOWN; 2637 LogFunc(("%s Link is down temporarily\n", pThis->szInst)); 2638 } 2503 2639 } 2504 2640 … … 2517 2653 if (LogIs7Enabled()) 2518 2654 { 2519 LogFunc(("%s", INSTANCE(pThis)));2655 LogFunc(("%s", pThis->szInst)); 2520 2656 switch(enmState) 2521 2657 { … … 2551 2687 if (fCachedLinkIsUp) 2552 2688 { 2553 Log(("%s Link is up\n", INSTANCE(pThis)));2689 Log(("%s Link is up\n", pThis->szInst)); 2554 2690 pThis->fCableConnected = true; 2555 2691 SET_LINK_UP(pThis); … … 2560 2696 /* The link was brought down explicitly, make sure it won't come up by timer. */ 2561 2697 PDMDevHlpTimerStop(pDevIns, pThisCC->hLinkUpTimer); 2562 Log(("%s Link is down\n", INSTANCE(pThis)));2698 Log(("%s Link is down\n", pThis->szInst)); 2563 2699 pThis->fCableConnected = false; 2564 2700 SET_LINK_DOWN(pThis); … … 2570 2706 return VINF_SUCCESS; 2571 2707 } 2708 /** 2709 * @interface_method_impl{PDMINETWORKCONFIG,pfnGetLinkState} 2710 */ 2711 static DECLCALLBACK(PDMNETWORKLINKSTATE) virtioNetR3NetworkConfig_GetLinkState(PPDMINETWORKCONFIG pInterface) 2712 { 2713 PVIRTIONETCC pThisCC = RT_FROM_MEMBER(pInterface, VIRTIONETCC, INetworkConfig); 2714 PVIRTIONET pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVIRTIONET); 2715 2716 return IS_LINK_UP(pThis) ? PDMNETWORKLINKSTATE_UP : PDMNETWORKLINKSTATE_DOWN; 2717 } 2572 2718 2573 2719 static int virtioNetR3DestroyWorkerThreads(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC) 2574 2720 { 2575 Log10Func(("%s\n", INSTANCE(pThis)));2721 Log10Func(("%s\n", pThis->szInst)); 2576 2722 int rc = VINF_SUCCESS; 2577 2723 for (unsigned idxWorker = 0; idxWorker < pThis->cWorkers; idxWorker++) 2578 2724 { 2579 PVIRTIONETWORKER pWorker = &pThis->aWorkers[idxWorker]; 2725 PVIRTIONETWORKER pWorker = &pThis->aWorkers[idxWorker]; 2726 PVIRTIONETWORKERR3 pWorkerR3 = &pThisCC->aWorkers[idxWorker]; 2727 2580 2728 if (pWorker->hEvtProcess != NIL_SUPSEMEVENT) 2581 2729 { … … 2583 2731 pWorker->hEvtProcess = NIL_SUPSEMEVENT; 2584 2732 } 2585 if (p ThisCC->aWorkers[idxWorker].pThread)2733 if (pWorkerR3->pThread) 2586 2734 { 2587 2735 int rcThread; 2588 rc = PDMDevHlpThreadDestroy(pDevIns, p ThisCC->aWorkers[idxWorker].pThread, &rcThread);2736 rc = PDMDevHlpThreadDestroy(pDevIns, pWorkerR3->pThread, &rcThread); 2589 2737 if (RT_FAILURE(rc) || RT_FAILURE(rcThread)) 2590 2738 AssertMsgFailed(("%s Failed to destroythread rc=%Rrc rcThread=%Rrc\n", __FUNCTION__, rc, rcThread)); 2591 pThisCC->aWorkers[idxWorker].pThread = NULL;2739 pWorkerR3->pThread = NULL; 2592 2740 } 2593 2741 } … … 2595 2743 } 2596 2744 2597 static int virtioNetR3CreateOneWorkerThread(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 2598 uint16_t idxWorker, uint16_t idxQueue) 2599 { 2600 Log10Func(("%s\n", INSTANCE(pThis))); 2601 int rc = VINF_SUCCESS; 2602 rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->aWorkers[idxWorker].hEvtProcess); 2745 static int virtioNetR3CreateOneWorkerThread(PPDMDEVINS pDevIns, PVIRTIONET pThis, uint16_t idxWorker, 2746 PVIRTIONETWORKER pWorker, PVIRTIONETWORKERR3 pWorkerR3, 2747 PVIRTIONETQUEUE pQueue) 2748 { 2749 Log10Func(("%s\n", pThis->szInst)); 2750 2751 int rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pWorker->hEvtProcess); 2603 2752 2604 2753 if (RT_FAILURE(rc)) … … 2606 2755 N_("DevVirtioNET: Failed to create SUP event semaphore")); 2607 2756 2608 LogFunc(("creating thread, idxWorker=%d, idxQueue=%d\n", idxWorker, idxQueue)); 2609 rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->aWorkers[idxWorker].pThread, 2610 (void *)(uintptr_t)idxWorker, virtioNetR3WorkerThread, 2611 virtioNetR3WakeupWorker, 0, RTTHREADTYPE_IO, VIRTQNAME(idxQueue)); 2612 if (rc != VINF_SUCCESS) 2613 { 2614 LogRel(("Error creating thread for Virtual Queue %s: %Rrc\n", VIRTQNAME(idxQueue), rc)); 2615 return rc; 2616 } 2617 pThisCC->aWorkers[idxWorker].idxQueue = idxQueue; 2618 pThis->afQueueAttached[idxQueue] = true; 2757 LogFunc(("creating thread for queue %s\n", pQueue->szName)); 2758 2759 rc = PDMDevHlpThreadCreate(pDevIns, &pWorkerR3->pThread, 2760 (void *)pWorker, virtioNetR3WorkerThread, 2761 virtioNetR3WakeupWorker, 0, RTTHREADTYPE_IO, pQueue->szName); 2762 if (RT_FAILURE(rc)) 2763 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 2764 N_("Error creating thread for Virtual Queue %s\n"), pQueue->idx); 2765 2766 pWorker->pQueue = pWorkerR3->pQueue = pQueue; 2767 pWorker->idx = pWorkerR3->idx = idxWorker; 2768 pQueue->pWorker = pWorker; 2769 pQueue->pWorkerR3 = pWorkerR3; 2770 pWorker->fAssigned = true; 2771 2772 LogFunc(("%s pThread: %p\n", pQueue->szName, pWorkerR3->pThread)); 2773 2619 2774 return rc; 2620 2775 } … … 2622 2777 static int virtioNetR3CreateWorkerThreads(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC) 2623 2778 { 2624 Log10Func(("%s\n", INSTANCE(pThis))); 2625 2626 int rc; 2627 uint16_t idxWorker = 0; 2628 for (uint16_t idxQueuePair = 0; idxQueuePair < pThis->cVirtqPairs; idxQueuePair++) 2629 { 2630 rc = virtioNetR3CreateOneWorkerThread(pDevIns, pThis, pThisCC, idxWorker, TXQIDX(idxQueuePair)); 2779 2780 #define CTRLWIDX 0 /* First worker is for the control queue */ 2781 2782 Log10Func(("%s\n", pThis->szInst)); 2783 2784 PVIRTIONETQUEUE pCtlQueue = &pThis->aQueues[CTRLQIDX]; 2785 int rc = virtioNetR3CreateOneWorkerThread(pDevIns, pThis, CTRLQIDX /* idxWorker */, 2786 &pThis->aWorkers[CTRLWIDX], &pThisCC->aWorkers[CTRLWIDX], pCtlQueue); 2787 AssertRCReturn(rc, rc); 2788 2789 pCtlQueue->fHasWorker = true; 2790 2791 uint16_t idxWorker = CTRLWIDX + 1; 2792 for (uint16_t idxQueuePair = 0; idxQueuePair < pThis->cVirtqPairs; idxQueuePair++, idxWorker++) 2793 { 2794 PVIRTIONETQUEUE pTxQueue = &pThis->aQueues[TXQIDX(idxQueuePair)]; 2795 PVIRTIONETQUEUE pRxQueue = &pThis->aQueues[RXQIDX(idxQueuePair)]; 2796 2797 rc = virtioNetR3CreateOneWorkerThread(pDevIns, pThis, idxWorker, &pThis->aWorkers[idxWorker], 2798 &pThisCC->aWorkers[idxWorker], pTxQueue); 2631 2799 AssertRCReturn(rc, rc); 2632 idxWorker++; 2633 } 2634 rc = virtioNetR3CreateOneWorkerThread(pDevIns, pThis, pThisCC, idxWorker, CTRLQIDX); 2635 pThis->cWorkers = idxWorker + 1; 2800 2801 pTxQueue->fHasWorker = true; 2802 pRxQueue->fHasWorker = false; 2803 } 2804 pThis->cWorkers = pThis->cVirtqPairs + 1; 2636 2805 return rc; 2637 2806 } 2807 2808 /** 2809 * @callback_method_impl{FNPDMTHREADDEV} 2810 */ 2811 static DECLCALLBACK(int) virtioNetR3WorkerThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 2812 { 2813 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 2814 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 2815 PVIRTIONETWORKER pWorker = (PVIRTIONETWORKER)pThread->pvUser; 2816 PVIRTIONETQUEUE pQueue = pWorker->pQueue; 2817 2818 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 2819 return VINF_SUCCESS; 2820 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 that causes the controlq activity to hang sporadically. See BugRef #8651, Comment #82 */ 2825 2826 virtioCoreQueueNotifyEnable(&pThis->Virtio, pQueue->idx, true /* fEnable */); 2827 2828 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 2829 { 2830 if (IS_VIRTQ_EMPTY(pDevIns, &pThis->Virtio, pQueue->idx)) 2831 { 2832 /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */ 2833 ASMAtomicWriteBool(&pWorker->fSleeping, true); 2834 bool fNotificationSent = ASMAtomicXchgBool(&pWorker->fNotified, false); 2835 if (!fNotificationSent) 2836 { 2837 Log10Func(("%s %s worker sleeping...\n\n", pThis->szInst, pQueue->szName)); 2838 Assert(ASMAtomicReadBool(&pWorker->fSleeping)); 2839 int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pWorker->hEvtProcess, RT_INDEFINITE_WAIT); 2840 STAM_COUNTER_INC(&pThis->StatTransmitByThread); 2841 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc); 2842 if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING)) 2843 return VINF_SUCCESS; 2844 if (rc == VERR_INTERRUPTED) 2845 continue; 2846 ASMAtomicWriteBool(&pWorker->fNotified, false); 2847 } 2848 ASMAtomicWriteBool(&pWorker->fSleeping, false); 2849 } 2850 2851 /* Dispatch to the handler for the queue this worker is set up to drive */ 2852 2853 if (!pThisCC->fQuiescing) 2854 { 2855 if (pQueue->fCtlQueue) 2856 { 2857 Log10Func(("%s %s worker woken. Fetching desc chain\n", pThis->szInst, pQueue->szName)); 2858 PVIRTIO_DESC_CHAIN_T pDescChain = NULL; 2859 int rc = virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, pQueue->idx, &pDescChain, true); 2860 if (rc == VERR_NOT_AVAILABLE) 2861 { 2862 Log10Func(("%s %s worker woken. Nothing found in queue/n", pThis->szInst, pQueue->szName)); 2863 continue; 2864 } 2865 virtioNetR3Ctrl(pDevIns, pThis, pThisCC, pDescChain); 2866 virtioCoreR3DescChainRelease(&pThis->Virtio, pDescChain); 2867 } 2868 else /* Must be Tx queue */ 2869 { 2870 Log10Func(("%s %s worker woken. Queue has data to transmit\n", pThis->szInst, pQueue->szName)); 2871 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pQueue, false /* fOnWorkerThread */); 2872 } 2873 2874 /* Rx queues aren't handled by our worker threads. Instead, the PDM network 2875 * leaf driver invokes PDMINETWORKDOWN.pfnWaitReceiveAvail() callback, 2876 * which waits until notified directly by virtioNetQueueNotified() 2877 * that guest IN buffers have been added to receive virt queue. 2878 */ 2879 } 2880 } 2881 Log10(("%s %s worker thread exiting\n", pThis->szInst, pQueue->szName)); 2882 return VINF_SUCCESS; 2883 } 2884 2638 2885 /** 2639 2886 * @callback_method_impl{VIRTIOCORER3,pfnStatusChanged} … … 2649 2896 { 2650 2897 LogFunc(("%s VirtIO ready\n-----------------------------------------------------------------------------------------\n", 2651 INSTANCE(pThis))); 2898 pThis->szInst)); 2899 2900 pThis->fNegotiatedFeatures = virtioCoreGetAcceptedFeatures(pVirtio); 2901 2902 #ifdef LOG_ENABLED 2903 virtioCorePrintFeatures(pVirtio, NULL); 2904 virtioNetPrintFeatures(pThis, NULL); 2905 #endif 2906 2652 2907 pThis->virtioNetConfig.uStatus = pThis->fCableConnected ? VIRTIONET_F_LINK_UP : 0; 2653 2908 2654 pThis->fResetting = false; 2655 pThisCC->fQuiescing = false; 2656 pThis->fNegotiatedFeatures = virtioCoreGetAcceptedFeatures(pVirtio); 2657 #ifdef LOG_ENABLED 2658 virtioPrintFeatures(pVirtio); 2659 virtioNetPrintFeatures(pThis); 2660 #endif 2909 pThis->fResetting = false; 2910 pThisCC->fQuiescing = false; 2911 2661 2912 for (unsigned idxQueue = 0; idxQueue < pThis->cVirtQueues; idxQueue++) 2662 2913 { 2663 (void) virtioCoreR3QueueAttach(&pThis->Virtio, idxQueue, VIRTQNAME(idxQueue)); 2664 pThis->afQueueAttached[idxQueue] = true; 2665 if (virtioCoreQueueIsEmpty(pThisCC->pDevIns, &pThis->Virtio, idxQueue)) 2666 virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, true); 2914 PVIRTIONETQUEUE pQueue = &pThis->aQueues[idxQueue]; 2915 pQueue->idx = idxQueue; 2916 (void) virtioCoreR3QueueAttach(&pThis->Virtio, pQueue->idx, pQueue->szName); 2917 pQueue->fAttachedToVirtioCore = true; 2918 if (IS_VIRTQ_EMPTY(pThisCC->pDevIns, &pThis->Virtio, pQueue->idx)) 2919 virtioCoreQueueNotifyEnable(&pThis->Virtio, pQueue->idx, true /* fEnable */); 2667 2920 } 2668 2921 } 2669 2922 else 2670 2923 { 2671 LogFunc(("%s VirtIO is resetting\n", INSTANCE(pThis)));2924 LogFunc(("%s VirtIO is resetting\n", pThis->szInst)); 2672 2925 2673 2926 pThis->virtioNetConfig.uStatus = pThis->fCableConnected ? VIRTIONET_F_LINK_UP : 0; 2674 Log7Func(("%s Link is %s\n", INSTANCE(pThis), pThis->fCableConnected ? "up" : "down"));2927 Log7Func(("%s Link is %s\n", pThis->szInst, pThis->fCableConnected ? "up" : "down")); 2675 2928 2676 2929 pThis->fPromiscuous = true; … … 2690 2943 pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, true); 2691 2944 2692 for (u nsignedidxQueue = 0; idxQueue < pThis->cVirtQueues; idxQueue++)2693 pThis->a fQueueAttached[idxQueue]= false;2945 for (uint16_t idxQueue = 0; idxQueue < pThis->cVirtQueues; idxQueue++) 2946 pThis->aQueues[idxQueue].fAttachedToVirtioCore = false; 2694 2947 } 2695 2948 } … … 2709 2962 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 2710 2963 2711 Log7Func(("%s\n", INSTANCE(pThis)));2964 Log7Func(("%s\n", pThis->szInst)); 2712 2965 AssertLogRelReturnVoid(iLUN == 0); 2713 2966 … … 2737 2990 RT_NOREF(fFlags); 2738 2991 2739 Log7Func(("%s", INSTANCE(pThis)));2992 Log7Func(("%s", pThis->szInst)); 2740 2993 2741 2994 AssertLogRelReturn(iLUN == 0, VERR_PDM_NO_SUCH_LUN); … … 2754 3007 else if ( rc == VERR_PDM_NO_ATTACHED_DRIVER 2755 3008 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME) 2756 Log(("%s No attached driver!\n", INSTANCE(pThis)));3009 Log(("%s No attached driver!\n", pThis->szInst)); 2757 3010 2758 3011 LEAVE_CRITICAL_SECTION; … … 2779 3032 { 2780 3033 PVIRTIONETR3 pThisCC = RT_FROM_MEMBER(pInterface, VIRTIONETCC, IBase); 2781 3034 LogFunc(("pInterface=%p %s\n", pInterface, pszIID)); 2782 3035 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKDOWN, &pThisCC->INetworkDown); 2783 3036 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThisCC->INetworkConfig); … … 2797 3050 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 2798 3051 2799 Log(("%s Destroying instance\n", INSTANCE(pThis)));3052 Log(("%s Destroying instance\n", pThis->szInst)); 2800 3053 2801 3054 if (pThis->hEventRxDescAvail != NIL_SUPSEMEVENT) … … 2828 3081 Log7Func(("PDM device instance: %d\n", iInstance)); 2829 3082 2830 RTStrPrintf(pThis->szInstanceName, sizeof(pThis->szInstanceName), "VIRTIONET%d", iInstance); 3083 RTStrPrintf(pThis->szInst, sizeof(pThis->szInst), "VNET%d", iInstance); 3084 3085 // Temporary for less logging clutter for singled-instance debugging 3086 *pThis->szInst = '\0'; 2831 3087 2832 3088 pThisCC->pDevIns = pDevIns; … … 2845 3101 pThisCC->INetworkConfig.pfnSetLinkState = virtioNetR3NetworkConfig_SetLinkState; 2846 3102 3103 pThis->hEventRxDescAvail = NIL_SUPSEMEVENT; 3104 2847 3105 /* 2848 3106 * Validate configuration. … … 2872 3130 if (pThis->cMsLinkUpDelay > 5000 || pThis->cMsLinkUpDelay < 100) 2873 3131 LogRel(("%s WARNING! Link up delay is set to %u seconds!\n", 2874 INSTANCE(pThis), pThis->cMsLinkUpDelay / 1000));2875 2876 Log(("%s Link up delay is set to %u seconds\n", INSTANCE(pThis), pThis->cMsLinkUpDelay / 1000));3132 pThis->szInst, pThis->cMsLinkUpDelay / 1000)); 3133 3134 Log(("%s Link up delay is set to %u seconds\n", pThis->szInst, pThis->cMsLinkUpDelay / 1000)); 2877 3135 2878 3136 /* Copy the MAC address configured for the VM to the MMIO accessible Virtio dev-specific config area */ … … 2886 3144 */ 2887 3145 2888 # if FEATURE_OFFERED(STATUS)2889 pThis->virtioNetConfig.uStatus = 0;2890 # endif2891 2892 # if FEATURE_OFFERED(MQ)2893 pThis->virtioNetConfig.uMaxVirtqPairs = VIRTIONET_MAX_QPAIRS;2894 # endif3146 # if FEATURE_OFFERED(STATUS) 3147 pThis->virtioNetConfig.uStatus = 0; 3148 # endif 3149 3150 # if FEATURE_OFFERED(MQ) 3151 pThis->virtioNetConfig.uMaxVirtqPairs = VIRTIONET_MAX_QPAIRS; 3152 # endif 2895 3153 2896 3154 /* Initialize the generic Virtio core: */ … … 2910 3168 2911 3169 /* 3170 * Create the semaphore that will be used to synchronize/throttle 3171 * the downstream LUN's Rx waiter thread. 3172 */ 3173 rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEventRxDescAvail); 3174 if (RT_FAILURE(rc)) 3175 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to create event semaphore")); 3176 3177 /* 2912 3178 * Initialize VirtIO core. This will result in a "status changed" callback 2913 3179 * when VirtIO is ready, at which time the Rx queue and ctrl queue worker threads will be created. 2914 3180 */ 2915 rc = virtioCoreR3Init(pDevIns, &pThis->Virtio, &pThisCC->Virtio, &VirtioPciParams, INSTANCE(pThis),3181 rc = virtioCoreR3Init(pDevIns, &pThis->Virtio, &pThisCC->Virtio, &VirtioPciParams, pThis->szInst, 2916 3182 VIRTIONET_HOST_FEATURES_OFFERED, 2917 3183 &pThis->virtioNetConfig /*pvDevSpecificCap*/, sizeof(pThis->virtioNetConfig)); … … 2923 3189 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-net: Required features not successfully negotiated.")); 2924 3190 2925 pThis->cVirtqPairs = pThis->fNegotiatedFeatures & VIRTIONET_F_MQ2926 ? pThis->virtioNetConfig.uMaxVirtqPairs :1;3191 pThis->cVirtqPairs = (pThis->fNegotiatedFeatures & VIRTIONET_F_MQ) 3192 ? pThis->virtioNetConfig.uMaxVirtqPairs : 1; 2927 3193 2928 3194 pThis->cVirtQueues += pThis->cVirtqPairs * 2 + 1; … … 2936 3202 */ 2937 3203 virtioNetR3SetVirtqNames(pThis); 3204 pThis->aQueues[CTRLQIDX].fCtlQueue = true; 2938 3205 2939 3206 /* … … 2945 3212 2946 3213 /* 2947 * Create the semaphore that will be used to synchronize/throttle2948 * the downstream LUN's Rx waiter thread.2949 */2950 rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEventRxDescAvail);2951 if (RT_FAILURE(rc))2952 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to create event semaphore"));2953 2954 /*2955 3214 * Attach network driver instance 2956 3215 */ … … 2964 3223 else if ( rc == VERR_PDM_NO_ATTACHED_DRIVER 2965 3224 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME) 2966 Log(("%s No attached driver!\n", INSTANCE(pThis)));3225 Log(("%s No attached driver!\n", pThis->szInst)); 2967 3226 2968 3227 /* … … 2982 3241 virtioNetR3SaveExec, virtioNetR3LoadExec); 2983 3242 AssertRCReturn(rc, rc); 2984 2985 2986 3243 2987 3244 /* … … 3017 3274 */ 3018 3275 char szTmp[128]; 3019 RTStrPrintf(szTmp, sizeof(szTmp), "%s%u", pDevIns->pReg->szName, pDevIns->iInstance); 3020 PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-net info", virtioNetR3Info); 3276 rc = PDMDevHlpDBGFInfoRegister(pDevIns, "virtio-net", "Display virtio-net info (help, net, features, state, pointers, queues, all)", virtioNetR3Info); 3277 if (RT_FAILURE(rc)) 3278 LogRel(("Failed to register DBGF info for device %s\n", szTmp)); 3021 3279 return rc; 3022 3280 }
Note:
See TracChangeset
for help on using the changeset viewer.