Changeset 81720 in vbox for trunk/src/VBox
- Timestamp:
- Nov 6, 2019 8:23:17 PM (5 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet.cpp
r81709 r81720 21 21 *********************************************************************************************************************************/ 22 22 #define LOG_GROUP LOG_GROUP_DEV_VIRTIO_NET 23 #define VNET_GC_SUPPORT24 23 #define VNET_WITH_GSO 25 24 #define VNET_WITH_MERGEABLE_RX_BUFS … … 32 31 #include <iprt/string.h> 33 32 #ifdef IN_RING3 34 # include <iprt/mem.h>35 33 # include <iprt/uuid.h> 36 34 #endif … … 46 44 47 45 #define INSTANCE(pThis) pThis->VPCI.szInstance 48 #define STATUS pThis->config.uStatus49 46 50 47 #ifdef IN_RING3 … … 52 49 # define VNET_PCI_CLASS 0x0200 53 50 # define VNET_N_QUEUES 3 54 # define VNET_NAME_FMT "VNet%d"55 51 56 52 # if 0 … … 58 54 # define VNET_PCI_CLASS 0x0180 59 55 # define VNET_N_QUEUES 2 60 # define VNET_NAME_FMT "VBlk%d"61 56 # endif 62 57 … … 113 108 114 109 /** 115 * Device state structure. Holds the current state of device.110 * The virtio-net shared instance data. 116 111 * 117 112 * @extends VPCISTATE 118 * @implements PDMINETWORKDOWN 119 * @implements PDMINETWORKCONFIG 120 */ 121 typedef struct VNetState_st 122 { 123 /* VPCISTATE must be the first member! */ 113 */ 114 typedef struct VNETSTATE 115 { 124 116 VPCISTATE VPCI; 125 117 126 118 // PDMCRITSECT csRx; /**< Protects RX queue. */ 127 119 128 PDMINETWORKDOWN INetworkDown;129 PDMINETWORKCONFIG INetworkConfig;130 R3PTRTYPE(PPDMIBASE) pDrvBase; /**< Attached network driver. */131 R3PTRTYPE(PPDMINETWORKUP) pDrv; /**< Connector of attached network driver. */132 133 /**< Link Up(/Restore) Timer. */134 PTMTIMERR3 pLinkUpTimer;135 136 120 #ifdef VNET_TX_DELAY 137 /**< Transmit Delay Timer - R3. */ 138 PTMTIMERR3 pTxTimerR3; 139 /**< Transmit Delay Timer - R0. */ 140 PTMTIMERR0 pTxTimerR0; 141 /**< Transmit Delay Timer - GC. */ 142 PTMTIMERRC pTxTimerRC; 143 144 # if HC_ARCH_BITS == 64 145 uint32_t padding2; 146 # endif 147 121 /** Transmit Delay Timer. */ 122 TMTIMERHANDLE hTxTimer; 148 123 uint32_t u32i; 149 124 uint32_t u32AvgDiff; … … 151 126 uint32_t u32MaxDiff; 152 127 uint64_t u64NanoTS; 153 #else /* !VNET_TX_DELAY */ 154 /** The support driver session handle. */ 155 R3R0PTRTYPE(PSUPDRVSESSION) pSupDrvSession; 128 #else /* !VNET_TX_DELAY */ 156 129 /** The event semaphore TX thread waits on. */ 157 SUPSEMEVENT hTxEvent; 158 R3PTRTYPE(PPDMTHREAD) pTxThread; 130 SUPSEMEVENT hTxEvent; 159 131 #endif /* !VNET_TX_DELAY */ 160 132 … … 184 156 bool fAllMulti; 185 157 /** The number of actually used slots in aMacTable. */ 186 uint32_t nMacFilterEntries;158 uint32_t cMacFilterEntries; 187 159 /** Array of MAC addresses accepted by RX filter. */ 188 160 RTMAC aMacFilter[VNET_MAC_FILTER_LEN]; … … 190 162 uint8_t aVlanFilter[VNET_MAX_VID / sizeof(uint8_t)]; 191 163 192 R3PTRTYPE(PVQUEUE) pRxQueue;193 R3PTRTYPE(PVQUEUE) pTxQueue;194 R3PTRTYPE(PVQUEUE) pCtlQueue;195 164 /* Receive-blocking-related fields ***************************************/ 196 165 197 166 /** EMT: Gets signalled when more RX descriptors become available. */ 198 167 SUPSEMEVENT hEventMoreRxDescAvail; 168 169 /** Handle of the I/O port range. */ 170 IOMIOPORTHANDLE hIoPorts; 199 171 200 172 /** @name Statistic … … 218 190 /** @} */ 219 191 } VNETSTATE; 220 /** Pointer to a virtual I/O network device state. */192 /** Pointer to the virtio-net shared instance data. */ 221 193 typedef VNETSTATE *PVNETSTATE; 194 195 196 /** 197 * The virtio-net ring-3 instance data. 198 * 199 * @extends VPCISTATER3 200 * @implements PDMINETWORKDOWN 201 * @implements PDMINETWORKCONFIG 202 */ 203 typedef struct VNETSTATER3 204 { 205 VPCISTATER3 VPCI; 206 207 PDMINETWORKDOWN INetworkDown; 208 PDMINETWORKCONFIG INetworkConfig; 209 R3PTRTYPE(PPDMIBASE) pDrvBase; /**< Attached network driver. */ 210 R3PTRTYPE(PPDMINETWORKUP) pDrv; /**< Connector of attached network driver. */ 211 /** The device instance. 212 * @note This is _only_ for use when dealing with interface callbacks. */ 213 PPDMDEVINSR3 pDevIns; 214 215 #ifndef VNET_TX_DELAY 216 R3PTRTYPE(PPDMTHREAD) pTxThread; 217 #endif 218 219 R3PTRTYPE(PVQUEUE) pRxQueue; 220 R3PTRTYPE(PVQUEUE) pTxQueue; 221 R3PTRTYPE(PVQUEUE) pCtlQueue; 222 223 /** Link Up(/Restore) Timer. */ 224 TMTIMERHANDLE hLinkUpTimer; 225 } VNETSTATER3; 226 /** Pointer to the virtio-net ring-3 instance data. */ 227 typedef VNETSTATER3 *PVNETSTATER3; 228 229 230 /** 231 * The virtio-net ring-0 instance data. 232 * 233 * @extends VPCISTATER0 234 */ 235 typedef struct VNETSTATER0 236 { 237 VPCISTATER0 VPCI; 238 } VNETSTATER0; 239 /** Pointer to the virtio-net ring-0 instance data. */ 240 typedef VNETSTATER0 *PVNETSTATER0; 241 242 243 /** 244 * The virtio-net raw-mode instance data. 245 * 246 * @extends VPCISTATERC 247 */ 248 typedef struct VNETSTATERC 249 { 250 VPCISTATERC VPCI; 251 } VNETSTATERC; 252 /** Pointer to the virtio-net ring-0 instance data. */ 253 typedef VNETSTATERC *PVNETSTATERC; 254 255 256 /** The virtio-net currenct context instance data. */ 257 typedef CTX_SUFF(VNETSTATE) VNETSTATECC; 258 /** Pointer to the virtio-net currenct context instance data. */ 259 typedef CTX_SUFF(PVNETSTATE) PVNETSTATECC; 260 261 222 262 223 263 #ifndef VBOX_DEVICE_STRUCT_TESTCASE … … 289 329 } 290 330 291 DECLINLINE(int) vnetR3CsEnter(P VNETSTATE pThis, int rcBusy)292 { 293 return vpciCsEnter( &pThis->VPCI, rcBusy);294 } 295 296 DECLINLINE(void) vnetR3CsLeave(P VNETSTATE pThis)297 { 298 vpciCsLeave( &pThis->VPCI);331 DECLINLINE(int) vnetR3CsEnter(PPDMDEVINS pDevIns, PVNETSTATE pThis, int rcBusy) 332 { 333 return vpciCsEnter(pDevIns, &pThis->VPCI, rcBusy); 334 } 335 336 DECLINLINE(void) vnetR3CsLeave(PPDMDEVINS pDevIns, PVNETSTATE pThis) 337 { 338 vpciCsLeave(pDevIns, &pThis->VPCI); 299 339 } 300 340 … … 322 362 * Dump a packet to debug log. 323 363 * 324 * @param pThis The device state structure.364 * @param pThis The virtio-net shared instance data. 325 365 * @param pbPacket The packet. 326 366 * @param cb The size of the packet. … … 346 386 * Print features given in uFeatures to debug log. 347 387 * 348 * @param pThis The device state structure.388 * @param pThis The virtio-net shared instance data. 349 389 * @param fFeatures Descriptions of which features to print. 350 390 * @param pcszText A string to print before the list of features. … … 482 522 * Hardware reset. Revert all registers to initial values. 483 523 */ 484 static DECLCALLBACK(int) vnetIoCb_Reset(PVPCISTATE pVPciState) 485 { 486 PVNETSTATE pThis = RT_FROM_MEMBER(pVPciState, VNETSTATE, VPCI); 524 static DECLCALLBACK(int) vnetIoCb_Reset(PPDMDEVINS pDevIns) 525 { 526 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 527 #ifdef IN_RING3 528 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 529 #endif 487 530 Log(("%s Reset triggered\n", INSTANCE(pThis))); 488 531 … … 493 536 return rc; 494 537 } 495 vpciReset( &pThis->VPCI);538 vpciReset(pDevIns, &pThis->VPCI); 496 539 vnetCsRxLeave(pThis); 497 540 498 541 /// @todo Implement reset 499 542 if (pThis->fCableConnected) 500 STATUS= VNET_S_LINK_UP;543 pThis->config.uStatus = VNET_S_LINK_UP; 501 544 else 502 STATUS= 0;545 pThis->config.uStatus = 0; 503 546 Log(("%s vnetIoCb_Reset: Link is %s\n", INSTANCE(pThis), pThis->fCableConnected ? "up" : "down")); 504 547 … … 509 552 pThis->fPromiscuous = true; 510 553 pThis->fAllMulti = false; 511 pThis-> nMacFilterEntries = 0;554 pThis->cMacFilterEntries = 0; 512 555 memset(pThis->aMacFilter, 0, VNET_MAC_FILTER_LEN * sizeof(RTMAC)); 513 556 memset(pThis->aVlanFilter, 0, sizeof(pThis->aVlanFilter)); … … 516 559 return VINF_IOM_R3_IOPORT_WRITE; 517 560 #else 518 if (pThis ->pDrv)519 pThis ->pDrv->pfnSetPromiscuousMode(pThis->pDrv, true);561 if (pThisCC->pDrv) 562 pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, true); 520 563 return VINF_SUCCESS; 521 564 #endif … … 544 587 * Helper function that raises an interrupt if the guest is ready to receive it. 545 588 */ 546 static int vnetR3RaiseInterrupt(P VNETSTATE pThis, int rcBusy, uint8_t u8IntCause)589 static int vnetR3RaiseInterrupt(PPDMDEVINS pDevIns, PVNETSTATE pThis, int rcBusy, uint8_t u8IntCause) 547 590 { 548 591 if (pThis->VPCI.uStatus & VPCI_STATUS_DRV_OK) 549 return vpciRaiseInterrupt( &pThis->VPCI, rcBusy, u8IntCause);592 return vpciRaiseInterrupt(pDevIns, &pThis->VPCI, rcBusy, u8IntCause); 550 593 return rcBusy; 551 594 } … … 561 604 * renegotiate any DHCP lease. 562 605 * 563 * @param pThis The Virtual I/O network device state. 564 */ 565 static void vnetR3TempLinkDown(PVNETSTATE pThis) 566 { 567 if (STATUS & VNET_S_LINK_UP) 568 { 569 STATUS &= ~VNET_S_LINK_UP; 570 vnetR3RaiseInterrupt(pThis, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 606 * @param pDevIns The device instance. 607 * @param pThis The virtio-net shared instance data. 608 * @param pThisCC The virtio-net ring-3 instance data. 609 */ 610 static void vnetR3TempLinkDown(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC) 611 { 612 if (pThis->config.uStatus & VNET_S_LINK_UP) 613 { 614 pThis->config.uStatus &= ~VNET_S_LINK_UP; 615 vnetR3RaiseInterrupt(pDevIns, pThis, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 571 616 /* Restore the link back in 5 seconds. */ 572 int rc = TMTimerSetMillies(pThis->pLinkUpTimer, pThis->cMsLinkUpDelay);617 int rc = PDMDevHlpTimerSetMillies(pDevIns, pThisCC->hLinkUpTimer, pThis->cMsLinkUpDelay); 573 618 AssertRC(rc); 574 619 Log(("%s vnetR3TempLinkDown: Link is down temporarily\n", INSTANCE(pThis))); … … 582 627 static DECLCALLBACK(void) vnetR3LinkUpTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 583 628 { 584 RT_NOREF(pTimer); 585 PVNETSTATE pThis = (PVNETSTATE)pvUser; 586 587 int rc = vnetR3CsEnter(pThis, VERR_SEM_BUSY); 588 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 589 return; 590 STATUS |= VNET_S_LINK_UP; 591 vnetR3RaiseInterrupt(pThis, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 629 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 630 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 631 RT_NOREF(pTimer, pvUser); 632 633 int rc = vnetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY); 634 AssertRCReturnVoid(rc); 635 636 pThis->config.uStatus |= VNET_S_LINK_UP; 637 vnetR3RaiseInterrupt(pDevIns, pThis, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 592 638 vnetWakeupReceive(pDevIns); 593 vnetR3CsLeave(pThis); 639 640 vnetR3CsLeave(pDevIns, pThis); 641 594 642 Log(("%s vnetR3LinkUpTimer: Link is up\n", INSTANCE(pThis))); 595 if (pThis ->pDrv)596 pThis ->pDrv->pfnNotifyLinkChanged(pThis->pDrv, PDMNETWORKLINKSTATE_UP);643 if (pThisCC->pDrv) 644 pThisCC->pDrv->pfnNotifyLinkChanged(pThisCC->pDrv, PDMNETWORKLINKSTATE_UP); 597 645 } 598 646 … … 604 652 * This function is called when the driver becomes ready. 605 653 */ 606 static DECLCALLBACK(void) vnetIoCb_Ready(PVPCISTATE pVPciState) 607 { 608 PVNETSTATE pThis = RT_FROM_MEMBER(pVPciState, VNETSTATE, VPCI); 609 Log(("%s Driver became ready, waking up RX thread...\n", INSTANCE(pThis))); 610 vnetWakeupReceive(pThis->VPCI.CTX_SUFF(pDevIns)); 654 static DECLCALLBACK(void) vnetIoCb_Ready(PPDMDEVINS pDevIns) 655 { 656 Log(("%s Driver became ready, waking up RX thread...\n", INSTANCE(PDMDEVINS_2_DATA(pDevIns, PVNETSTATE)))); 657 vnetWakeupReceive(pDevIns); 611 658 } 612 659 … … 628 675 629 676 /** 630 * @callback_method_impl{FNIOMIOPORT IN}631 */ 632 PDMBOTHCBDECL(int) vnetIOPortIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb)677 * @callback_method_impl{FNIOMIOPORTNEWIN} 678 */ 679 static DECLCALLBACK(VBOXSTRICTRC) vnetIOPortIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) 633 680 { 634 681 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 635 682 RT_NOREF(pvUser); 636 return vpciIOPortIn(pDevIns, &pThis->VPCI, port, pu32, cb, &g_IOCallbacks); 637 } 638 639 640 /** 641 * @callback_method_impl{FNIOMIOPORTOUT} 642 */ 643 PDMBOTHCBDECL(int) vnetIOPortOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t u32, unsigned cb) 644 { 645 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 683 return vpciIOPortIn(pDevIns, &pThis->VPCI, offPort, pu32, cb, &g_IOCallbacks); 684 } 685 686 687 /** 688 * @callback_method_impl{FNIOMIOPORTNEWOUT} 689 */ 690 static DECLCALLBACK(VBOXSTRICTRC) vnetIOPortOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) 691 { 692 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 693 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 646 694 RT_NOREF(pvUser); 647 return vpciIOPortOut(pDevIns, &pThis->VPCI, port, u32, cb, &g_IOCallbacks);695 return vpciIOPortOut(pDevIns, &pThis->VPCI, &pThisCC->VPCI, offPort, u32, cb, &g_IOCallbacks); 648 696 } 649 697 … … 660 708 * 661 709 * @returns VERR_NET_NO_BUFFER_SPACE if it cannot. 662 * @param pInterface Pointer to the interface structure containing the called function pointer.663 710 * @thread RX 664 711 */ 665 static int vnetR3CanReceive(P VNETSTATE pThis)712 static int vnetR3CanReceive(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC) 666 713 { 667 714 int rc = vnetCsRxEnter(pThis, VERR_SEM_BUSY); … … 671 718 if (!(pThis->VPCI.uStatus & VPCI_STATUS_DRV_OK)) 672 719 rc = VERR_NET_NO_BUFFER_SPACE; 673 else if (!vqueueIsReady( &pThis->VPCI, pThis->pRxQueue))720 else if (!vqueueIsReady(pThisCC->pRxQueue)) 674 721 rc = VERR_NET_NO_BUFFER_SPACE; 675 else if (vqueueIsEmpty( &pThis->VPCI, pThis->pRxQueue))676 { 677 vringSetNotification( &pThis->VPCI, &pThis->pRxQueue->VRing, true);722 else if (vqueueIsEmpty(pDevIns, pThisCC->pRxQueue)) 723 { 724 vringSetNotification(pDevIns, &pThisCC->pRxQueue->VRing, true); 678 725 rc = VERR_NET_NO_BUFFER_SPACE; 679 726 } 680 727 else 681 728 { 682 vringSetNotification( &pThis->VPCI, &pThis->pRxQueue->VRing, false);729 vringSetNotification(pDevIns, &pThisCC->pRxQueue->VRing, false); 683 730 rc = VINF_SUCCESS; 684 731 } … … 694 741 static DECLCALLBACK(int) vnetR3NetworkDown_WaitReceiveAvail(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies) 695 742 { 696 PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkDown); 697 PPDMDEVINS pDevIns = pThis->VPCI.pDevInsR3; 743 PVNETSTATECC pThisCC = RT_FROM_MEMBER(pInterface, VNETSTATECC, INetworkDown); 744 PPDMDEVINS pDevIns = pThisCC->pDevIns; 745 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 698 746 LogFlow(("%s vnetR3NetworkDown_WaitReceiveAvail(cMillies=%u)\n", INSTANCE(pThis), cMillies)); 699 747 700 int rc = vnetR3CanReceive(p This);748 int rc = vnetR3CanReceive(pDevIns, pThis, pThisCC); 701 749 if (RT_SUCCESS(rc)) 702 750 return VINF_SUCCESS; … … 710 758 711 759 VMSTATE enmVMState; 712 while (RT_LIKELY( (enmVMState = PDMDevHlpVMState(p This->VPCI.CTX_SUFF(pDevIns))) == VMSTATE_RUNNING760 while (RT_LIKELY( (enmVMState = PDMDevHlpVMState(pDevIns)) == VMSTATE_RUNNING 713 761 || enmVMState == VMSTATE_RUNNING_LS)) 714 762 { 715 int rc2 = vnetR3CanReceive(p This);763 int rc2 = vnetR3CanReceive(pDevIns, pThis, pThisCC); 716 764 if (RT_SUCCESS(rc2)) 717 765 { … … 733 781 734 782 /** 735 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 783 * @interface_method_impl{PDMIBASE,pfnQueryInterface, 784 * For VNETSTATECC::VPCI.IBase} 736 785 */ 737 786 static DECLCALLBACK(void *) vnetQueryInterface(struct PDMIBASE *pInterface, const char *pszIID) 738 787 { 739 PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, VPCI.IBase);740 Assert(&pThis->VPCI.IBase == pInterface); 741 742 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORK DOWN, &pThis->INetworkDown);743 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThis->INetworkConfig); 744 return vpci QueryInterface(pInterface, pszIID);788 PVNETSTATECC pThisCC = RT_FROM_MEMBER(pInterface, VNETSTATECC, VPCI.IBase); 789 790 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKDOWN, &pThisCC->INetworkDown); 791 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThisCC->INetworkConfig); 792 793 return vpciR3QueryInterface(&pThisCC->VPCI, pszIID); 745 794 } 746 795 … … 802 851 Log4(("%s vnetR3AddressFilter: %RTmac (conf) != %RTmac (dest)\n", INSTANCE(pThis), pThis->config.mac.au8, pvBuf)); 803 852 804 for (unsigned i = 0; i < pThis-> nMacFilterEntries; i++)853 for (unsigned i = 0; i < pThis->cMacFilterEntries; i++) 805 854 if (!memcmp(&pThis->aMacFilter[i], pvBuf, sizeof(RTMAC))) 806 855 return true; … … 819 868 * 820 869 * @returns VBox status code. 821 * @param pThis The device state structure. 870 * @param pDevIns The device instance. 871 * @param pThis The virtio-net shared instance data. 822 872 * @param pvBuf The available data. 823 873 * @param cb Number of bytes available in the buffer. 824 874 * @thread RX 825 875 */ 826 static int vnetR3HandleRxPacket(PVNETSTATE pThis, const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso) 876 static int vnetR3HandleRxPacket(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC, 877 const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso) 827 878 { 828 879 VNETHDRMRX Hdr; … … 877 928 unsigned int nSeg = 0, uElemSize = 0, cbReserved = 0; 878 929 879 if (!vqueueGet( &pThis->VPCI, pThis->pRxQueue, &elem))930 if (!vqueueGet(pDevIns, &pThis->VPCI, pThisCC->pRxQueue, &elem)) 880 931 { 881 932 /* … … 921 972 } 922 973 STAM_PROFILE_START(&pThis->StatReceiveStore, a); 923 vqueuePut( &pThis->VPCI, pThis->pRxQueue, &elem, uElemSize, cbReserved);974 vqueuePut(pDevIns, &pThis->VPCI, pThisCC->pRxQueue, &elem, uElemSize, cbReserved); 924 975 STAM_PROFILE_STOP(&pThis->StatReceiveStore, a); 925 976 if (!vnetR3MergeableRxBuffers(pThis)) … … 930 981 { 931 982 Hdr.u16NumBufs = nElem; 932 int rc = PDMDevHlpPCIPhysWrite(p This->VPCI.CTX_SUFF(pDevIns), addrHdrMrx,983 int rc = PDMDevHlpPCIPhysWrite(pDevIns, addrHdrMrx, 933 984 &Hdr, sizeof(Hdr)); 934 985 if (RT_FAILURE(rc)) … … 938 989 } 939 990 } 940 vqueueSync( &pThis->VPCI, pThis->pRxQueue);991 vqueueSync(pDevIns, &pThis->VPCI, pThisCC->pRxQueue); 941 992 if (uOffset < cb) 942 993 { … … 951 1002 * @interface_method_impl{PDMINETWORKDOWN,pfnReceiveGso} 952 1003 */ 953 static DECLCALLBACK(int) vnetR3NetworkDown_ReceiveGso(PPDMINETWORKDOWN pInterface, 954 const void *pvBuf, size_t cb, 955 PCPDMNETWORKGSO pGso) 956 { 957 PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkDown); 1004 static DECLCALLBACK(int) vnetR3NetworkDown_ReceiveGso(PPDMINETWORKDOWN pInterface, const void *pvBuf, 1005 size_t cb, PCPDMNETWORKGSO pGso) 1006 { 1007 PVNETSTATECC pThisCC = RT_FROM_MEMBER(pInterface, VNETSTATECC, INetworkDown); 1008 PPDMDEVINS pDevIns = pThisCC->pDevIns; 1009 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 958 1010 959 1011 if (pGso) … … 985 1037 986 1038 Log2(("%s vnetR3NetworkDown_ReceiveGso: pvBuf=%p cb=%u pGso=%p\n", INSTANCE(pThis), pvBuf, cb, pGso)); 987 int rc = vnetR3CanReceive(p This);1039 int rc = vnetR3CanReceive(pDevIns, pThis, pThisCC); 988 1040 if (RT_FAILURE(rc)) 989 1041 return rc; 990 1042 991 1043 /* Drop packets if VM is not running or cable is disconnected. */ 992 VMSTATE enmVMState = PDMDevHlpVMState(p This->VPCI.CTX_SUFF(pDevIns));1044 VMSTATE enmVMState = PDMDevHlpVMState(pDevIns); 993 1045 if (( enmVMState != VMSTATE_RUNNING 994 1046 && enmVMState != VMSTATE_RUNNING_LS) 995 || !( STATUS& VNET_S_LINK_UP))1047 || !(pThis->config.uStatus & VNET_S_LINK_UP)) 996 1048 return VINF_SUCCESS; 997 1049 998 1050 STAM_PROFILE_START(&pThis->StatReceive, a); 999 vpci SetReadLed(&pThis->VPCI, true);1051 vpciR3SetReadLed(&pThis->VPCI, true); 1000 1052 if (vnetR3AddressFilter(pThis, pvBuf, cb)) 1001 1053 { … … 1003 1055 if (RT_SUCCESS(rc)) 1004 1056 { 1005 rc = vnetR3HandleRxPacket(p This, pvBuf, cb, pGso);1057 rc = vnetR3HandleRxPacket(pDevIns, pThis, pThisCC, pvBuf, cb, pGso); 1006 1058 STAM_REL_COUNTER_ADD(&pThis->StatReceiveBytes, cb); 1007 1059 vnetCsRxLeave(pThis); 1008 1060 } 1009 1061 } 1010 vpci SetReadLed(&pThis->VPCI, false);1062 vpciR3SetReadLed(&pThis->VPCI, false); 1011 1063 STAM_PROFILE_STOP(&pThis->StatReceive, a); 1012 1064 return rc; … … 1022 1074 1023 1075 /** 1024 * Gets the current Media Access Control (MAC) address. 1025 * 1026 * @returns VBox status code. 1027 * @param pInterface Pointer to the interface structure containing the called function pointer. 1028 * @param pMac Where to store the MAC address. 1029 * @thread EMT 1076 * @interface_method_impl{PDMINETWORKCONFIG,pfnGetMac} 1030 1077 */ 1031 1078 static DECLCALLBACK(int) vnetR3NetworkConfig_GetMac(PPDMINETWORKCONFIG pInterface, PRTMAC pMac) 1032 1079 { 1033 PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkConfig); 1080 PVNETSTATECC pThisCC = RT_FROM_MEMBER(pInterface, VNETSTATECC, INetworkConfig); 1081 PVNETSTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVNETSTATE); 1034 1082 memcpy(pMac, pThis->config.mac.au8, sizeof(RTMAC)); 1035 1083 return VINF_SUCCESS; … … 1037 1085 1038 1086 /** 1039 * Gets the new link state. 1040 * 1041 * @returns The current link state. 1042 * @param pInterface Pointer to the interface structure containing the called function pointer. 1043 * @thread EMT 1087 * @interface_method_impl{PDMINETWORKCONFIG,pfnGetLinkState} 1044 1088 */ 1045 1089 static DECLCALLBACK(PDMNETWORKLINKSTATE) vnetR3NetworkConfig_GetLinkState(PPDMINETWORKCONFIG pInterface) 1046 1090 { 1047 PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkConfig); 1048 if (STATUS & VNET_S_LINK_UP) 1091 PVNETSTATECC pThisCC = RT_FROM_MEMBER(pInterface, VNETSTATECC, INetworkConfig); 1092 PVNETSTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVNETSTATE); 1093 if (pThis->config.uStatus & VNET_S_LINK_UP) 1049 1094 return PDMNETWORKLINKSTATE_UP; 1050 1095 return PDMNETWORKLINKSTATE_DOWN; 1051 1096 } 1052 1097 1053 1054 /** 1055 * Sets the new link state. 1056 * 1057 * @returns VBox status code. 1058 * @param pInterface Pointer to the interface structure containing the called function pointer. 1059 * @param enmState The new link state 1098 /** 1099 * @interface_method_impl{PDMINETWORKCONFIG,pfnSetLinkState} 1060 1100 */ 1061 1101 static DECLCALLBACK(int) vnetR3NetworkConfig_SetLinkState(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState) 1062 1102 { 1063 PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkConfig); 1064 bool fOldUp = !!(STATUS & VNET_S_LINK_UP); 1103 PVNETSTATECC pThisCC = RT_FROM_MEMBER(pInterface, VNETSTATECC, INetworkConfig); 1104 PPDMDEVINS pDevIns = pThisCC->pDevIns; 1105 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 1106 bool fOldUp = !!(pThis->config.uStatus & VNET_S_LINK_UP); 1065 1107 bool fNewUp = enmState == PDMNETWORKLINKSTATE_UP; 1066 1108 … … 1074 1116 * notification will be sent when the link actually goes up in vnetR3LinkUpTimer(). 1075 1117 */ 1076 vnetR3TempLinkDown(p This);1077 if (pThis ->pDrv)1078 pThis ->pDrv->pfnNotifyLinkChanged(pThis->pDrv, enmState);1118 vnetR3TempLinkDown(pDevIns, pThis, pThisCC); 1119 if (pThisCC->pDrv) 1120 pThisCC->pDrv->pfnNotifyLinkChanged(pThisCC->pDrv, enmState); 1079 1121 } 1080 1122 } … … 1085 1127 Log(("%s Link is up\n", INSTANCE(pThis))); 1086 1128 pThis->fCableConnected = true; 1087 STATUS|= VNET_S_LINK_UP;1088 vnetR3RaiseInterrupt(p This, VERR_SEM_BUSY, VPCI_ISR_CONFIG);1129 pThis->config.uStatus |= VNET_S_LINK_UP; 1130 vnetR3RaiseInterrupt(pDevIns, pThis, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 1089 1131 } 1090 1132 else 1091 1133 { 1092 1134 /* The link was brought down explicitly, make sure it won't come up by timer. */ 1093 TMTimerStop(pThis->pLinkUpTimer);1135 PDMDevHlpTimerStop(pDevIns, pThisCC->hLinkUpTimer); 1094 1136 Log(("%s Link is down\n", INSTANCE(pThis))); 1095 1137 pThis->fCableConnected = false; 1096 STATUS&= ~VNET_S_LINK_UP;1097 vnetR3RaiseInterrupt(p This, VERR_SEM_BUSY, VPCI_ISR_CONFIG);1098 } 1099 if (pThis ->pDrv)1100 pThis ->pDrv->pfnNotifyLinkChanged(pThis->pDrv, enmState);1138 pThis->config.uStatus &= ~VNET_S_LINK_UP; 1139 vnetR3RaiseInterrupt(pDevIns, pThis, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 1140 } 1141 if (pThisCC->pDrv) 1142 pThisCC->pDrv->pfnNotifyLinkChanged(pThisCC->pDrv, enmState); 1101 1143 } 1102 1144 return VINF_SUCCESS; 1103 1145 } 1104 1146 1105 static DECLCALLBACK(void) vnetR3QueueReceive(PPDMDEVINS pDevIns, PVPCISTATE pVPciState, PVQUEUE pQueue) 1106 { 1107 PVNETSTATE pThis = RT_FROM_MEMBER(pVPciState, VNETSTATE, VPCI); 1147 /** 1148 * @callback_method_impl{FNVPCIQUEUECALLBACK, The RX queue} 1149 */ 1150 static DECLCALLBACK(void) vnetR3QueueReceive(PPDMDEVINS pDevIns, PVQUEUE pQueue) 1151 { 1152 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 1108 1153 RT_NOREF(pThis, pQueue); 1109 1154 Log(("%s Receive buffers has been added, waking up receive thread.\n", INSTANCE(pThis))); … … 1177 1222 AssertReturnVoid(uStart < cbSize); 1178 1223 AssertReturnVoid(uStart + uOffset + sizeof(uint16_t) <= cbSize); 1179 *(uint16_t *)(pBuf + uStart + uOffset) = vnetR3CSum16(pBuf + uStart, cbSize - uStart);1180 } 1181 1182 static bool vnetR3ReadHeader(P VNETSTATE pThis, RTGCPHYS GCPhys, PVNETHDR pHdr, uint32_t cbMax)1183 { 1184 int rc = PDMDevHlpPhysRead(p This->VPCI.CTX_SUFF(pDevIns), GCPhys, pHdr, sizeof(*pHdr)); /** @todo r=bird: Why not PDMDevHlpPCIPhysRead? */1224 *(uint16_t *)(pBuf + uStart + uOffset) = vnetR3CSum16(pBuf + uStart, cbSize - uStart); 1225 } 1226 1227 static bool vnetR3ReadHeader(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, PVNETHDR pHdr, uint32_t cbMax) 1228 { 1229 int rc = PDMDevHlpPhysRead(pDevIns, GCPhys, pHdr, sizeof(*pHdr)); /** @todo r=bird: Why not PDMDevHlpPCIPhysRead? */ 1185 1230 if (RT_FAILURE(rc)) 1186 1231 return false; … … 1223 1268 } 1224 1269 1225 static int vnetR3TransmitFrame(PVNETSTATE pThis, PPDMSCATTERGATHER pSgBuf, PPDMNETWORKGSO pGso, PVNETHDR pHdr) 1270 static int vnetR3TransmitFrame(PVNETSTATE pThis, PVNETSTATECC pThisCC, PPDMSCATTERGATHER pSgBuf, 1271 PPDMNETWORKGSO pGso, PVNETHDR pHdr) 1226 1272 { 1227 1273 vnetR3PacketDump(pThis, (uint8_t *)pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, "--> Outgoing"); … … 1270 1316 } 1271 1317 1272 return pThis->pDrv->pfnSendBuf(pThis->pDrv, pSgBuf, false); 1273 } 1274 1275 static void vnetR3TransmitPendingPackets(PVNETSTATE pThis, PVQUEUE pQueue, bool fOnWorkerThread) 1318 return pThisCC->pDrv->pfnSendBuf(pThisCC->pDrv, pSgBuf, false); 1319 } 1320 1321 static void vnetR3TransmitPendingPackets(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC, 1322 PVQUEUE pQueue, bool fOnWorkerThread) 1276 1323 { 1277 1324 /* … … 1295 1342 } 1296 1343 1297 PPDMINETWORKUP pDrv = pThis ->pDrv;1344 PPDMINETWORKUP pDrv = pThisCC->pDrv; 1298 1345 if (pDrv) 1299 1346 { … … 1314 1361 1315 1362 Log3(("%s vnetR3TransmitPendingPackets: About to transmit %d pending packets\n", 1316 INSTANCE(pThis), vringReadAvailIndex( &pThis->VPCI, &pThis->pTxQueue->VRing) - pThis->pTxQueue->uNextAvailIndex));1317 1318 vpci SetWriteLed(&pThis->VPCI, true);1363 INSTANCE(pThis), vringReadAvailIndex(pDevIns, &pThisCC->pTxQueue->VRing) - pThisCC->pTxQueue->uNextAvailIndex)); 1364 1365 vpciR3SetWriteLed(&pThis->VPCI, true); 1319 1366 1320 1367 /* … … 1323 1370 */ 1324 1371 VQUEUEELEM elem; /* This bugger is big! ~48KB on 64-bit hosts. */ 1325 while (vqueuePeek( &pThis->VPCI, pQueue, &elem))1372 while (vqueuePeek(pDevIns, &pThis->VPCI, pQueue, &elem)) 1326 1373 { 1327 1374 unsigned int uOffset = 0; … … 1347 1394 if (uSize > VNET_MAX_FRAME_SIZE) 1348 1395 uSize = VNET_MAX_FRAME_SIZE; 1349 if (pThis ->pDrv && vnetR3ReadHeader(pThis, elem.aSegsOut[0].addr, &Hdr, uSize))1396 if (pThisCC->pDrv && vnetR3ReadHeader(pDevIns, elem.aSegsOut[0].addr, &Hdr, uSize)) 1350 1397 { 1351 1398 RT_UNTRUSTED_VALIDATED_FENCE(); … … 1358 1405 /** @todo Optimize away the extra copying! (lazy bird) */ 1359 1406 PPDMSCATTERGATHER pSgBuf; 1360 int rc = pThis ->pDrv->pfnAllocBuf(pThis->pDrv, uSize, pGso, &pSgBuf);1407 int rc = pThisCC->pDrv->pfnAllocBuf(pThisCC->pDrv, uSize, pGso, &pSgBuf); 1361 1408 if (RT_SUCCESS(rc)) 1362 1409 { … … 1368 1415 { 1369 1416 unsigned int cbSegment = RT_MIN(uSize, elem.aSegsOut[i].cb); 1370 PDMDevHlpPhysRead(p This->VPCI.CTX_SUFF(pDevIns), elem.aSegsOut[i].addr,1417 PDMDevHlpPhysRead(pDevIns, elem.aSegsOut[i].addr, 1371 1418 ((uint8_t*)pSgBuf->aSegs[0].pvSeg) + uOffset, 1372 1419 cbSegment); … … 1374 1421 uSize -= cbSegment; 1375 1422 } 1376 rc = vnetR3TransmitFrame(pThis, p SgBuf, pGso, &Hdr);1423 rc = vnetR3TransmitFrame(pThis, pThisCC, pSgBuf, pGso, &Hdr); 1377 1424 } 1378 1425 else … … 1390 1437 1391 1438 /* Remove this descriptor chain from the available ring */ 1392 vqueueSkip( &pThis->VPCI, pQueue);1393 vqueuePut( &pThis->VPCI, pQueue, &elem, sizeof(VNETHDR) + uOffset);1394 vqueueSync( &pThis->VPCI, pQueue);1439 vqueueSkip(pDevIns, &pThis->VPCI, pQueue); 1440 vqueuePut(pDevIns, &pThis->VPCI, pQueue, &elem, sizeof(VNETHDR) + uOffset); 1441 vqueueSync(pDevIns, &pThis->VPCI, pQueue); 1395 1442 STAM_PROFILE_ADV_STOP(&pThis->StatTransmit, a); 1396 1443 } 1397 vpci SetWriteLed(&pThis->VPCI, false);1444 vpciR3SetWriteLed(&pThis->VPCI, false); 1398 1445 1399 1446 if (pDrv) … … 1407 1454 static DECLCALLBACK(void) vnetR3NetworkDown_XmitPending(PPDMINETWORKDOWN pInterface) 1408 1455 { 1409 PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkDown); 1456 PVNETSTATECC pThisCC = RT_FROM_MEMBER(pInterface, VNETSTATECC, INetworkDown); 1457 PPDMDEVINS pDevIns = pThisCC->pDevIns; 1458 PVNETSTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVNETSTATE); 1410 1459 STAM_COUNTER_INC(&pThis->StatTransmitByNetwork); 1411 vnetR3TransmitPendingPackets(p This, pThis->pTxQueue, false /*fOnWorkerThread*/);1460 vnetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pThisCC->pTxQueue, false /*fOnWorkerThread*/); 1412 1461 } 1413 1462 1414 1463 # ifdef VNET_TX_DELAY 1415 1464 1416 static DECLCALLBACK(void) vnetR3QueueTransmit(PPDMDEVINS pDevIns, PVPCISTATE pVPciState, PVQUEUE pQueue) 1417 { 1418 PVNETSTATE pThis = RT_FROM_MEMBER(pVPciState, VNETSTATE, VPCI); 1419 RT_NOREF(pDevIns); 1420 1421 if (TMTimerIsActive(pThis->CTX_SUFF(pTxTimer))) 1422 { 1423 TMTimerStop(pThis->CTX_SUFF(pTxTimer)); 1465 /** 1466 * @callback_method_impl{FNVPCIQUEUECALLBACK, The TX queue} 1467 */ 1468 static DECLCALLBACK(void) vnetR3QueueTransmit(PPDMDEVINS pDevIns, PVQUEUE pQueue) 1469 { 1470 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 1471 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 1472 1473 if (PDMDevHlpTimerIsActive(pDevIns, pThis->hTxTimer)) 1474 { 1475 PDMDevHlpTimerStop(pDevIns, pThis->hTxTimer); 1424 1476 Log3(("%s vnetR3QueueTransmit: Got kicked with notification disabled, re-enable notification and flush TX queue\n", INSTANCE(pThis))); 1425 vnetR3TransmitPendingPackets(p This, pQueue, false /*fOnWorkerThread*/);1426 if (RT_FAILURE(vnetR3CsEnter(p This, VERR_SEM_BUSY)))1477 vnetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pQueue, false /*fOnWorkerThread*/); 1478 if (RT_FAILURE(vnetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY))) 1427 1479 LogRel(("vnetR3QueueTransmit: Failed to enter critical section!/n")); 1428 1480 else 1429 1481 { 1430 vringSetNotification( &pThis->VPCI, &pThis->pTxQueue->VRing, true);1431 vnetR3CsLeave(p This);1482 vringSetNotification(pDevIns, &pThisCC->pTxQueue->VRing, true); 1483 vnetR3CsLeave(pDevIns, pThis); 1432 1484 } 1433 1485 } 1434 1486 else 1435 1487 { 1436 if (RT_FAILURE(vnetR3CsEnter(p This, VERR_SEM_BUSY)))1488 if (RT_FAILURE(vnetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY))) 1437 1489 LogRel(("vnetR3QueueTransmit: Failed to enter critical section!/n")); 1438 1490 else 1439 1491 { 1440 vringSetNotification( &pThis->VPCI, &pThis->pTxQueue->VRing, false);1441 TMTimerSetMicro(pThis->CTX_SUFF(pTxTimer), VNET_TX_DELAY);1492 vringSetNotification(pDevIns, &pThisCC->pTxQueue->VRing, false); 1493 PDMDevHlpTimerSetMicro(pDevIns, pThis->hTxTimer, VNET_TX_DELAY); 1442 1494 pThis->u64NanoTS = RTTimeNanoTS(); 1443 vnetR3CsLeave(p This);1495 vnetR3CsLeave(pDevIns, pThis); 1444 1496 } 1445 1497 } … … 1451 1503 static DECLCALLBACK(void) vnetR3TxTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 1452 1504 { 1453 RT_NOREF(pDevIns, pTimer); 1454 PVNETSTATE pThis = (PVNETSTATE)pvUser; 1455 1456 uint32_t u32MicroDiff = (uint32_t)((RTTimeNanoTS() - pThis->u64NanoTS)/1000); 1505 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 1506 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 1507 RT_NOREF(pTimer, pvUser); 1508 1509 uint32_t u32MicroDiff = (uint32_t)((RTTimeNanoTS() - pThis->u64NanoTS) / 1000); 1457 1510 if (u32MicroDiff < pThis->u32MinDiff) 1458 1511 pThis->u32MinDiff = u32MicroDiff; … … 1465 1518 1466 1519 // Log3(("%s vnetR3TxTimer: Expired\n", INSTANCE(pThis))); 1467 vnetR3TransmitPendingPackets(p This, pThis->pTxQueue, false /*fOnWorkerThread*/);1468 if (RT_FAILURE(vnetR3CsEnter(p This, VERR_SEM_BUSY)))1520 vnetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pThisCC->pTxQueue, false /*fOnWorkerThread*/); 1521 if (RT_FAILURE(vnetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY))) 1469 1522 { 1470 1523 LogRel(("vnetR3TxTimer: Failed to enter critical section!/n")); 1471 1524 return; 1472 1525 } 1473 vringSetNotification( &pThis->VPCI, &pThis->pTxQueue->VRing, true);1474 vnetR3CsLeave(p This);1475 } 1476 1477 DECLINLINE(int) vnetR3CreateTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis )1478 { 1479 RT_NOREF(pDevIns, pThis );1526 vringSetNotification(pDevIns, &pThisCC->pTxQueue->VRing, true); 1527 vnetR3CsLeave(pDevIns, pThis); 1528 } 1529 1530 DECLINLINE(int) vnetR3CreateTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC) 1531 { 1532 RT_NOREF(pDevIns, pThis, pThisCC); 1480 1533 return VINF_SUCCESS; 1481 1534 } 1482 1535 1483 DECLINLINE(void) vnetR3DestroyTxThreadAndEvent(P VNETSTATE pThis)1484 { 1485 RT_NOREF(p This);1536 DECLINLINE(void) vnetR3DestroyTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC) 1537 { 1538 RT_NOREF(pDevIns, pThis, pThisCC); 1486 1539 } 1487 1540 1488 1541 # else /* !VNET_TX_DELAY */ 1489 1542 1543 /** 1544 * @callback_method_impl{FNPDMTHREADDEV} 1545 */ 1490 1546 static DECLCALLBACK(int) vnetR3TxThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 1491 1547 { 1492 RT_NOREF(pDevIns); 1493 PVNETSTATE pThis = (PVNETSTATE)pThread->pvUser; 1494 int rc = VINF_SUCCESS; 1548 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 1549 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 1495 1550 1496 1551 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 1497 1552 return VINF_SUCCESS; 1498 1553 1554 int rc = VINF_SUCCESS; 1499 1555 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 1500 1556 { … … 1505 1561 while (true) 1506 1562 { 1507 vnetR3TransmitPendingPackets(p This, pThis->pTxQueue, false /*fOnWorkerThread*/); /// @todo shouldn't it be true instead?1563 vnetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pThisCC->pTxQueue, false /*fOnWorkerThread*/); /// @todo shouldn't it be true instead? 1508 1564 Log(("vnetR3TxThread: enable kicking and get to sleep\n")); 1509 vringSetNotification( &pThis->VPCI, &pThis->pTxQueue->VRing, true);1510 if (vqueueIsEmpty( &pThis->VPCI, pThis->pTxQueue))1565 vringSetNotification(pDevIns, &pThisCC->pTxQueue->VRing, true); 1566 if (vqueueIsEmpty(pDevIns, pThisCC->pTxQueue)) 1511 1567 break; 1512 vringSetNotification( &pThis->VPCI, &pThis->pTxQueue->VRing, false);1568 vringSetNotification(pDevIns, &pThisCC->pTxQueue->VRing, false); 1513 1569 } 1514 1570 } … … 1518 1574 1519 1575 /** 1520 * Unblock TX thread so it can respond to a state change. 1521 * 1522 * @returns VBox status code. 1523 * @param pDevIns The device instance. 1524 * @param pThread The send thread. 1576 * @callback_method_impl{FNPDMTHREADWAKEUPDEV} 1525 1577 */ 1526 1578 static DECLCALLBACK(int) vnetR3TxThreadWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 1527 1579 { 1528 PVNETSTATE pThis = (PVNETSTATE)pThread->pvUser; 1580 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 1581 RT_NOREF(pThread); 1529 1582 return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hTxEvent); 1530 1583 } 1531 1584 1532 static int vnetR3CreateTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis )1585 static int vnetR3CreateTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC) 1533 1586 { 1534 1587 int rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hTxEvent); 1535 if (RT_FAILURE(rc)) 1536 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("VNET: Failed to create SUP event semaphore")); 1537 1538 rc = PDMDevHlpThreadCreate(pDevIns, &pThis->pTxThread, pThis, vnetR3TxThread, 1539 vnetR3TxThreadWakeUp, 0, RTTHREADTYPE_IO, INSTANCE(pThis)); 1540 if (RT_FAILURE(rc)) 1541 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("VNET: Failed to create worker thread %s"), INSTANCE(pThis)); 1542 return VINF_SUCCESS; 1543 } 1544 1545 static void vnetR3DestroyTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis) 1546 { 1547 if (pThis->pTxThread) 1548 { 1588 if (RT_SUCCESS(rc)) 1589 { 1590 rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->pTxThread, NULL, vnetR3TxThread, 1591 vnetR3TxThreadWakeUp, 0, RTTHREADTYPE_IO, INSTANCE(pThis)); 1592 if (RT_FAILURE(rc)) 1593 PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("VNET: Failed to create worker thread %s"), INSTANCE(pThis)); 1594 } 1595 else 1596 PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("VNET: Failed to create SUP event semaphore")); 1597 return rc; 1598 } 1599 1600 static void vnetR3DestroyTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC) 1601 { 1602 if (pThisCC->pTxThread) 1603 { 1604 /* Destroy the thread. */ 1549 1605 int rcThread; 1550 /* Destroy the thread. */ 1551 int rc = PDMR3ThreadDestroy(pThis->pTxThread, &rcThread); 1606 int rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->pTxThread, &rcThread); 1552 1607 if (RT_FAILURE(rc) || RT_FAILURE(rcThread)) 1553 1608 AssertMsgFailed(("%s Failed to destroy async IO thread rc=%Rrc rcThread=%Rrc\n", __FUNCTION__, rc, rcThread)); 1554 pThis->pTxThread = NULL; 1555 } 1609 pThisCC->pTxThread = NULL; 1610 } 1611 1556 1612 if (pThis->hTxEvent != NIL_SUPSEMEVENT) 1557 1613 { … … 1561 1617 } 1562 1618 1563 static DECLCALLBACK(void) vnetR3QueueTransmit(PPDMDEVINS pDevIns, PVPCISTATE pVPciState, PVQUEUE pQueue) 1564 { 1565 PVNETSTATE pThis = RT_FROM_MEMBER(pVPciState, VNETSTATE, VPCI); 1619 /** 1620 * @callback_method_impl{FNVPCIQUEUECALLBACK, The TX queue} 1621 */ 1622 static DECLCALLBACK(void) vnetR3QueueTransmit(PPDMDEVINS pDevIns, PVQUEUE pQueue) 1623 { 1624 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 1566 1625 1567 1626 Log(("vnetR3QueueTransmit: disable kicking and wake up TX thread\n")); 1568 vringSetNotification(&pThis->VPCI, &pQueue->VRing, false); 1569 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hTxEvent); 1627 vringSetNotification(pDevIns, &pQueue->VRing, false); 1628 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hTxEvent); 1629 AssertRC(rc); 1570 1630 } 1571 1631 1572 1632 # endif /* !VNET_TX_DELAY */ 1573 1633 1574 static uint8_t vnetR3ControlRx(PVNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem) 1634 static uint8_t vnetR3ControlRx(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC, 1635 PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem) 1575 1636 { 1576 1637 uint8_t u8Ack = VNET_OK; 1577 1638 uint8_t fOn, fDrvWasPromisc = pThis->fPromiscuous | pThis->fAllMulti; 1578 PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), 1579 pElem->aSegsOut[1].addr, 1580 &fOn, sizeof(fOn)); 1639 PDMDevHlpPhysRead(pDevIns, pElem->aSegsOut[1].addr, &fOn, sizeof(fOn)); 1581 1640 Log(("%s vnetR3ControlRx: uCommand=%u fOn=%u\n", INSTANCE(pThis), pCtlHdr->u8Command, fOn)); 1582 1641 switch (pCtlHdr->u8Command) … … 1591 1650 u8Ack = VNET_ERROR; 1592 1651 } 1593 if (fDrvWasPromisc != (pThis->fPromiscuous | pThis->fAllMulti) && pThis ->pDrv)1594 pThis ->pDrv->pfnSetPromiscuousMode(pThis->pDrv,1652 if (fDrvWasPromisc != (pThis->fPromiscuous | pThis->fAllMulti) && pThisCC->pDrv) 1653 pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, 1595 1654 (pThis->fPromiscuous | pThis->fAllMulti)); 1596 1655 … … 1598 1657 } 1599 1658 1600 static uint8_t vnetR3ControlMac(P VNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)1659 static uint8_t vnetR3ControlMac(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem) 1601 1660 { 1602 1661 uint32_t nMacs = 0; 1603 1662 1604 if ( pCtlHdr->u8Command != VNET_CTRL_CMD_MAC_TABLE_SET1663 if ( pCtlHdr->u8Command != VNET_CTRL_CMD_MAC_TABLE_SET 1605 1664 || pElem->nOut != 3 1606 1665 || pElem->aSegsOut[1].cb < sizeof(nMacs) … … 1613 1672 1614 1673 /* Load unicast addresses */ 1615 PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), 1616 pElem->aSegsOut[1].addr, 1617 &nMacs, sizeof(nMacs)); 1674 PDMDevHlpPhysRead(pDevIns, pElem->aSegsOut[1].addr, &nMacs, sizeof(nMacs)); 1618 1675 1619 1676 if (pElem->aSegsOut[1].cb < nMacs * sizeof(RTMAC) + sizeof(nMacs)) … … 1632 1689 { 1633 1690 if (nMacs) 1634 PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), 1635 pElem->aSegsOut[1].addr + sizeof(nMacs), 1636 pThis->aMacFilter, nMacs * sizeof(RTMAC)); 1637 pThis->nMacFilterEntries = nMacs; 1638 #ifdef DEBUG 1691 PDMDevHlpPhysRead(pDevIns, pElem->aSegsOut[1].addr + sizeof(nMacs), pThis->aMacFilter, nMacs * sizeof(RTMAC)); 1692 pThis->cMacFilterEntries = nMacs; 1693 #ifdef LOG_ENABLED 1639 1694 Log(("%s vnetR3ControlMac: unicast macs:\n", INSTANCE(pThis))); 1640 1695 for(unsigned i = 0; i < nMacs; i++) 1641 1696 Log((" %RTmac\n", &pThis->aMacFilter[i])); 1642 #endif /* DEBUG */1697 #endif 1643 1698 } 1644 1699 1645 1700 /* Load multicast addresses */ 1646 PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), 1647 pElem->aSegsOut[2].addr, 1648 &nMacs, sizeof(nMacs)); 1701 PDMDevHlpPhysRead(pDevIns, pElem->aSegsOut[2].addr, &nMacs, sizeof(nMacs)); 1649 1702 1650 1703 if (pElem->aSegsOut[2].cb < nMacs * sizeof(RTMAC) + sizeof(nMacs)) … … 1655 1708 } 1656 1709 1657 if (nMacs > VNET_MAC_FILTER_LEN - pThis-> nMacFilterEntries)1710 if (nMacs > VNET_MAC_FILTER_LEN - pThis->cMacFilterEntries) 1658 1711 { 1659 1712 Log(("%s vnetR3ControlMac: MAC table is too big, have to use allmulti mode (nMacs=%u)\n", INSTANCE(pThis), nMacs)); … … 1663 1716 { 1664 1717 if (nMacs) 1665 PDMDevHlpPhysRead(p This->VPCI.CTX_SUFF(pDevIns),1718 PDMDevHlpPhysRead(pDevIns, 1666 1719 pElem->aSegsOut[2].addr + sizeof(nMacs), 1667 &pThis->aMacFilter[pThis-> nMacFilterEntries],1720 &pThis->aMacFilter[pThis->cMacFilterEntries], 1668 1721 nMacs * sizeof(RTMAC)); 1669 #ifdef DEBUG1722 #ifdef LOG_ENABLED 1670 1723 Log(("%s vnetR3ControlMac: multicast macs:\n", INSTANCE(pThis))); 1671 1724 for(unsigned i = 0; i < nMacs; i++) 1672 1725 Log((" %RTmac\n", 1673 &pThis->aMacFilter[i+pThis-> nMacFilterEntries]));1674 #endif /* DEBUG */1675 pThis-> nMacFilterEntries += nMacs;1726 &pThis->aMacFilter[i+pThis->cMacFilterEntries])); 1727 #endif 1728 pThis->cMacFilterEntries += nMacs; 1676 1729 } 1677 1730 … … 1679 1732 } 1680 1733 1681 static uint8_t vnetR3ControlVlan(P VNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)1734 static uint8_t vnetR3ControlVlan(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem) 1682 1735 { 1683 1736 uint8_t u8Ack = VNET_OK; … … 1691 1744 } 1692 1745 1693 PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), 1694 pElem->aSegsOut[1].addr, 1695 &u16Vid, sizeof(u16Vid)); 1746 PDMDevHlpPhysRead(pDevIns, pElem->aSegsOut[1].addr, &u16Vid, sizeof(u16Vid)); 1696 1747 1697 1748 if (u16Vid >= VNET_MAX_VID) … … 1719 1770 1720 1771 1721 static DECLCALLBACK(void) vnetR3QueueControl(PPDMDEVINS pDevIns, PVPCISTATE pVPciState, PVQUEUE pQueue) 1722 { 1723 PVNETSTATE pThis = RT_FROM_MEMBER(pVPciState, VNETSTATE, VPCI); 1724 VQUEUEELEM elem; 1725 while (vqueueGet(&pThis->VPCI, pQueue, &elem)) 1772 /** 1773 * @callback_method_impl{FNVPCIQUEUECALLBACK, The CLT queue} 1774 */ 1775 static DECLCALLBACK(void) vnetR3QueueControl(PPDMDEVINS pDevIns, PVQUEUE pQueue) 1776 { 1777 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 1778 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 1779 1780 VQUEUEELEM elem; 1781 while (vqueueGet(pDevIns, &pThis->VPCI, pQueue, &elem)) 1726 1782 { 1727 1783 if (elem.nOut < 1 || elem.aSegsOut[0].cb < sizeof(VNETCTLHDR)) … … 1745 1801 { 1746 1802 case VNET_CTRL_CLS_RX_MODE: 1747 bAck = vnetR3ControlRx(p This, &CtlHdr, &elem);1803 bAck = vnetR3ControlRx(pDevIns, pThis, pThisCC, &CtlHdr, &elem); 1748 1804 break; 1749 1805 case VNET_CTRL_CLS_MAC: 1750 bAck = vnetR3ControlMac(p This, &CtlHdr, &elem);1806 bAck = vnetR3ControlMac(pDevIns, pThis, &CtlHdr, &elem); 1751 1807 break; 1752 1808 case VNET_CTRL_CLS_VLAN: 1753 bAck = vnetR3ControlVlan(p This, &CtlHdr, &elem);1809 bAck = vnetR3ControlVlan(pDevIns, pThis, &CtlHdr, &elem); 1754 1810 break; 1755 1811 default: … … 1759 1815 PDMDevHlpPCIPhysWrite(pDevIns, elem.aSegsIn[elem.nIn - 1].addr, &bAck, sizeof(bAck)); 1760 1816 1761 vqueuePut(&pThis->VPCI, pQueue, &elem, sizeof(bAck)); 1762 vqueueSync(&pThis->VPCI, pQueue); 1763 } 1817 vqueuePut(pDevIns, &pThis->VPCI, pQueue, &elem, sizeof(bAck)); 1818 vqueueSync(pDevIns, &pThis->VPCI, pQueue); 1819 } 1820 } 1821 1822 /* -=-=-=-=- Debug info item -=-=-=-=- */ 1823 1824 /** 1825 * @callback_method_impl{FNDBGFINFOARGVDEV} 1826 */ 1827 static DECLCALLBACK(void) vnetR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs) 1828 { 1829 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 1830 RT_NOREF(cArgs, papszArgs); 1831 vpcR3iDumpStateWorker(&pThis->VPCI, pHlp); 1764 1832 } 1765 1833 … … 1819 1887 1820 1888 /* Save the common part */ 1821 int rc = vpci SaveExec(&pThis->VPCI, pSSM);1889 int rc = vpciR3SaveExec(pHlp, &pThis->VPCI, pSSM); 1822 1890 AssertRCReturn(rc, rc); 1823 1891 … … 1826 1894 pHlp->pfnSSMPutBool( pSSM, pThis->fPromiscuous); 1827 1895 pHlp->pfnSSMPutBool( pSSM, pThis->fAllMulti); 1828 pHlp->pfnSSMPutU32( pSSM, pThis-> nMacFilterEntries);1829 pHlp->pfnSSMPutMem( pSSM, pThis->aMacFilter, pThis-> nMacFilterEntries * sizeof(RTMAC));1896 pHlp->pfnSSMPutU32( pSSM, pThis->cMacFilterEntries); 1897 pHlp->pfnSSMPutMem( pSSM, pThis->aMacFilter, pThis->cMacFilterEntries * sizeof(RTMAC)); 1830 1898 rc = pHlp->pfnSSMPutMem(pSSM, pThis->aVlanFilter, sizeof(pThis->aVlanFilter)); 1831 1899 AssertRCReturn(rc, rc); … … 1858 1926 { 1859 1927 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 1928 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 1860 1929 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 1861 1930 … … 1868 1937 LogRel(("%s: The mac address differs: config=%RTmac saved=%RTmac\n", INSTANCE(pThis), &pThis->macConfigured, &macConfigured)); 1869 1938 1870 rc = vpci LoadExec(&pThis->VPCI, pSSM, uVersion, uPass, VNET_N_QUEUES);1939 rc = vpciR3LoadExec(pHlp, &pThis->VPCI, pSSM, uVersion, uPass, VNET_N_QUEUES); 1871 1940 AssertRCReturn(rc, rc); 1872 1941 … … 1880 1949 pHlp->pfnSSMGetBool(pSSM, &pThis->fPromiscuous); 1881 1950 pHlp->pfnSSMGetBool(pSSM, &pThis->fAllMulti); 1882 pHlp->pfnSSMGetU32(pSSM, &pThis-> nMacFilterEntries);1883 pHlp->pfnSSMGetMem(pSSM, pThis->aMacFilter, pThis-> nMacFilterEntries * sizeof(RTMAC));1951 pHlp->pfnSSMGetU32(pSSM, &pThis->cMacFilterEntries); 1952 pHlp->pfnSSMGetMem(pSSM, pThis->aMacFilter, pThis->cMacFilterEntries * sizeof(RTMAC)); 1884 1953 1885 1954 /* Clear the rest. */ 1886 if (pThis-> nMacFilterEntries < VNET_MAC_FILTER_LEN)1887 memset(&pThis->aMacFilter[pThis-> nMacFilterEntries],1955 if (pThis->cMacFilterEntries < VNET_MAC_FILTER_LEN) 1956 memset(&pThis->aMacFilter[pThis->cMacFilterEntries], 1888 1957 0, 1889 (VNET_MAC_FILTER_LEN - pThis-> nMacFilterEntries) * sizeof(RTMAC));1958 (VNET_MAC_FILTER_LEN - pThis->cMacFilterEntries) * sizeof(RTMAC)); 1890 1959 rc = pHlp->pfnSSMGetMem(pSSM, pThis->aVlanFilter, sizeof(pThis->aVlanFilter)); 1891 1960 AssertRCReturn(rc, rc); … … 1895 1964 pThis->fPromiscuous = true; 1896 1965 pThis->fAllMulti = false; 1897 pThis-> nMacFilterEntries = 0;1966 pThis->cMacFilterEntries = 0; 1898 1967 memset(pThis->aMacFilter, 0, VNET_MAC_FILTER_LEN * sizeof(RTMAC)); 1899 1968 memset(pThis->aVlanFilter, 0, sizeof(pThis->aVlanFilter)); 1900 if (pThis ->pDrv)1901 pThis ->pDrv->pfnSetPromiscuousMode(pThis->pDrv, true);1969 if (pThisCC->pDrv) 1970 pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, true); 1902 1971 } 1903 1972 } … … 1913 1982 static DECLCALLBACK(int) vnetR3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 1914 1983 { 1984 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 1985 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 1915 1986 RT_NOREF(pSSM); 1916 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 1917 1918 if (pThis->pDrv) 1919 pThis->pDrv->pfnSetPromiscuousMode(pThis->pDrv, 1920 (pThis->fPromiscuous | pThis->fAllMulti)); 1987 1988 if (pThisCC->pDrv) 1989 pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, (pThis->fPromiscuous | pThis->fAllMulti)); 1921 1990 /* 1922 1991 * Indicate link down to the guest OS that all network connections have … … 1924 1993 */ 1925 1994 if (!PDMDevHlpVMTeleportedAndNotFullyResumedYet(pDevIns)) 1926 vnetR3TempLinkDown(p This);1995 vnetR3TempLinkDown(pDevIns, pThis, pThisCC); 1927 1996 1928 1997 return VINF_SUCCESS; … … 1930 1999 1931 2000 1932 /* -=-=-=-=- PCI Device -=-=-=-=- */1933 1934 /**1935 * @callback_method_impl{FNPCIIOREGIONMAP}1936 */1937 static DECLCALLBACK(int) vnetR3Map(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,1938 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)1939 {1940 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);1941 RT_NOREF(pPciDev, iRegion);1942 1943 if (enmType != PCI_ADDRESS_SPACE_IO)1944 {1945 /* We should never get here */1946 AssertMsgFailed(("Invalid PCI address space param in map callback"));1947 return VERR_INTERNAL_ERROR;1948 }1949 1950 pThis->VPCI.IOPortBase = (RTIOPORT)GCPhysAddress;1951 int rc = PDMDevHlpIOPortRegister(pDevIns, pThis->VPCI.IOPortBase,1952 cb, 0, vnetIOPortOut, vnetIOPortIn,1953 NULL, NULL, "VirtioNet");1954 #ifdef VNET_GC_SUPPORT1955 AssertRCReturn(rc, rc);1956 rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->VPCI.IOPortBase,1957 cb, 0, "vnetIOPortOut", "vnetIOPortIn",1958 NULL, NULL, "VirtioNet");1959 AssertRCReturn(rc, rc);1960 rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->VPCI.IOPortBase,1961 cb, 0, "vnetIOPortOut", "vnetIOPortIn",1962 NULL, NULL, "VirtioNet");1963 #endif1964 AssertRC(rc);1965 return rc;1966 }1967 1968 1969 2001 /* -=-=-=-=- PDMDEVREG -=-=-=-=- */ 1970 2002 … … 1974 2006 static DECLCALLBACK(void) vnetR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 1975 2007 { 2008 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 2009 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 2010 Log(("%s vnetR3Detach:\n", INSTANCE(pThis))); 1976 2011 RT_NOREF(fFlags); 1977 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);1978 Log(("%s vnetR3Detach:\n", INSTANCE(pThis)));1979 2012 1980 2013 AssertLogRelReturnVoid(iLUN == 0); 1981 2014 1982 int rc = vnetR3CsEnter(p This, VERR_SEM_BUSY);2015 int rc = vnetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY); 1983 2016 if (RT_FAILURE(rc)) 1984 2017 { … … 1987 2020 } 1988 2021 1989 vnetR3DestroyTxThreadAndEvent(pDevIns, pThis );2022 vnetR3DestroyTxThreadAndEvent(pDevIns, pThis, pThisCC); 1990 2023 1991 2024 /* 1992 2025 * Zero important members. 1993 2026 */ 1994 pThis ->pDrvBase = NULL;1995 pThis ->pDrv= NULL;1996 1997 vnetR3CsLeave(p This);2027 pThisCC->pDrvBase = NULL; 2028 pThisCC->pDrv = NULL; 2029 2030 vnetR3CsLeave(pDevIns, pThis); 1998 2031 } 1999 2032 … … 2004 2037 static DECLCALLBACK(int) vnetR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 2005 2038 { 2039 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 2040 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 2006 2041 RT_NOREF(fFlags); 2007 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);2008 2042 LogFlow(("%s vnetR3Attach:\n", INSTANCE(pThis))); 2009 2043 2010 2044 AssertLogRelReturn(iLUN == 0, VERR_PDM_NO_SUCH_LUN); 2011 2045 2012 int rc = vnetR3CsEnter(p This, VERR_SEM_BUSY);2046 int rc = vnetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY); 2013 2047 if (RT_FAILURE(rc)) 2014 2048 { … … 2020 2054 * Attach the driver. 2021 2055 */ 2022 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis ->VPCI.IBase, &pThis->pDrvBase, "Network Port");2056 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThisCC->VPCI.IBase, &pThisCC->pDrvBase, "Network Port"); 2023 2057 if (RT_SUCCESS(rc)) 2024 2058 { … … 2033 2067 #endif 2034 2068 } 2035 pThis ->pDrv = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMINETWORKUP);2036 AssertMsgStmt(pThis ->pDrv, ("Failed to obtain the PDMINETWORKUP interface!\n"),2069 pThisCC->pDrv = PDMIBASE_QUERY_INTERFACE(pThisCC->pDrvBase, PDMINETWORKUP); 2070 AssertMsgStmt(pThisCC->pDrv, ("Failed to obtain the PDMINETWORKUP interface!\n"), 2037 2071 rc = VERR_PDM_MISSING_INTERFACE_BELOW); 2038 2072 2039 vnetR3CreateTxThreadAndEvent(pDevIns, pThis );2073 vnetR3CreateTxThreadAndEvent(pDevIns, pThis, pThisCC); 2040 2074 } 2041 2075 else if ( rc == VERR_PDM_NO_ATTACHED_DRIVER … … 2053 2087 */ 2054 2088 if (RT_SUCCESS(rc)) 2055 vnetR3TempLinkDown(p This);2056 2057 vnetR3CsLeave(p This);2089 vnetR3TempLinkDown(pDevIns, pThis, pThisCC); 2090 2091 vnetR3CsLeave(pDevIns, pThis); 2058 2092 return rc; 2059 2060 2093 } 2061 2094 … … 2078 2111 /* Poke thread waiting for buffer space. */ 2079 2112 vnetWakeupReceive(pDevIns); 2080 }2081 2082 2083 /**2084 * @interface_method_impl{PDMDEVREGR3,pfnRelocate}2085 */2086 static DECLCALLBACK(void) vnetR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)2087 {2088 vpciRelocate(pDevIns, offDelta);2089 #ifdef VNET_TX_DELAY2090 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);2091 pThis->pTxTimerRC = TMTimerRCPtr(pThis->pTxTimerR3);2092 #endif2093 2113 } 2094 2114 … … 2117 2137 // PDMR3CritSectDelete(&pThis->csRx); 2118 2138 2119 return vpci Destruct(&pThis->VPCI);2139 return vpciR3Term(pDevIns, &pThis->VPCI); 2120 2140 } 2121 2141 … … 2128 2148 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 2129 2149 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 2150 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 2130 2151 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 2131 2152 int rc; … … 2134 2155 * Initialize the instance data suffiencently for the destructor not to blow up. 2135 2156 */ 2136 pThis->hEventMoreRxDescAvail = NIL_SUPSEMEVENT; 2157 RTStrPrintf(pThis->VPCI.szInstance, sizeof(pThis->VPCI.szInstance), "VNet%d", iInstance); 2158 pThisCC->pDevIns = pDevIns; 2159 pThis->hEventMoreRxDescAvail = NIL_SUPSEMEVENT; 2137 2160 #ifndef VNET_TX_DELAY 2138 pThis->hTxEvent = NIL_SUPSEMEVENT;2139 pThis ->pTxThread= NULL;2161 pThis->hTxEvent = NIL_SUPSEMEVENT; 2162 pThisCC->pTxThread = NULL; 2140 2163 #endif 2164 2165 /* Initialize state structure */ 2166 pThis->u32PktNo = 1; 2167 2168 /* Interfaces */ 2169 pThisCC->INetworkDown.pfnWaitReceiveAvail = vnetR3NetworkDown_WaitReceiveAvail; 2170 pThisCC->INetworkDown.pfnReceive = vnetR3NetworkDown_Receive; 2171 pThisCC->INetworkDown.pfnReceiveGso = vnetR3NetworkDown_ReceiveGso; 2172 pThisCC->INetworkDown.pfnXmitPending = vnetR3NetworkDown_XmitPending; 2173 2174 pThisCC->INetworkConfig.pfnGetMac = vnetR3NetworkConfig_GetMac; 2175 pThisCC->INetworkConfig.pfnGetLinkState = vnetR3NetworkConfig_GetLinkState; 2176 pThisCC->INetworkConfig.pfnSetLinkState = vnetR3NetworkConfig_SetLinkState; 2177 2141 2178 2142 2179 /* Do our own locking. */ … … 2144 2181 AssertRCReturn(rc, rc); 2145 2182 2146 /* Initialize PCI part. */ 2147 pThis->VPCI.IBase.pfnQueryInterface = vnetQueryInterface; 2148 2149 rc = vpciConstruct(pDevIns, &pThis->VPCI, iInstance, VNET_NAME_FMT, VIRTIO_NET_ID, VNET_PCI_CLASS, VNET_N_QUEUES); 2183 /* 2184 * Initialize VPCI part. 2185 */ 2186 pThisCC->VPCI.IBase.pfnQueryInterface = vnetQueryInterface; 2187 2188 rc = vpciR3Init(pDevIns, &pThis->VPCI, &pThisCC->VPCI, VIRTIO_NET_ID, VNET_PCI_CLASS, VNET_N_QUEUES); 2150 2189 AssertRCReturn(rc, rc); 2151 2190 2152 pThis->pRxQueue = vpciAddQueue(&pThis->VPCI, 256, vnetR3QueueReceive, "RX "); 2153 pThis->pTxQueue = vpciAddQueue(&pThis->VPCI, 256, vnetR3QueueTransmit, "TX "); 2154 pThis->pCtlQueue = vpciAddQueue(&pThis->VPCI, 16, vnetR3QueueControl, "CTL"); 2191 pThisCC->pRxQueue = vpciR3AddQueue(&pThis->VPCI, &pThisCC->VPCI, 256, vnetR3QueueReceive, "RX "); 2192 pThisCC->pTxQueue = vpciR3AddQueue(&pThis->VPCI, &pThisCC->VPCI, 256, vnetR3QueueTransmit, "TX "); 2193 pThisCC->pCtlQueue = vpciR3AddQueue(&pThis->VPCI, &pThisCC->VPCI, 16, vnetR3QueueControl, "CTL"); 2194 AssertLogRelReturn(pThisCC->pCtlQueue && pThisCC->pTxQueue && pThisCC->pRxQueue, VERR_INTERNAL_ERROR_5); 2155 2195 2156 2196 Log(("%s Constructing new instance\n", INSTANCE(pThis))); … … 2182 2222 pThis->config.uStatus = 0; 2183 2223 2184 /* Initialize state structure */2185 pThis->u32PktNo = 1;2186 2187 /* Interfaces */2188 pThis->INetworkDown.pfnWaitReceiveAvail = vnetR3NetworkDown_WaitReceiveAvail;2189 pThis->INetworkDown.pfnReceive = vnetR3NetworkDown_Receive;2190 pThis->INetworkDown.pfnReceiveGso = vnetR3NetworkDown_ReceiveGso;2191 pThis->INetworkDown.pfnXmitPending = vnetR3NetworkDown_XmitPending;2192 2193 pThis->INetworkConfig.pfnGetMac = vnetR3NetworkConfig_GetMac;2194 pThis->INetworkConfig.pfnGetLinkState = vnetR3NetworkConfig_GetLinkState;2195 pThis->INetworkConfig.pfnSetLinkState = vnetR3NetworkConfig_SetLinkState;2196 2197 2224 /* Initialize critical section. */ 2198 2225 // char szTmp[sizeof(pThis->VPCI.szInstance) + 2]; … … 2203 2230 2204 2231 /* Map our ports to IO space. */ 2205 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, VPCI_CONFIG + sizeof(VNetPCIConfig), PCI_ADDRESS_SPACE_IO, vnetR3Map); 2232 rc = PDMDevHlpPCIIORegionCreateIo(pDevIns, 0 /*iPciReion*/, VPCI_CONFIG + sizeof(VNetPCIConfig), 2233 vnetIOPortOut, vnetIOPortIn, NULL /*pvUser*/, "VirtioNet", NULL /*paExtDescs*/, 2234 &pThis->hIoPorts); 2206 2235 AssertRCReturn(rc, rc); 2207 2236 … … 2214 2243 2215 2244 /* Create Link Up Timer */ 2216 rc = PDMDevHlpT MTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vnetR3LinkUpTimer, pThis, TMTIMER_FLAGS_NO_CRIT_SECT,2217 "VirtioNet Link Up Timer", &pThis->pLinkUpTimer);2245 rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vnetR3LinkUpTimer, NULL, TMTIMER_FLAGS_NO_CRIT_SECT, 2246 "VirtioNet Link Up Timer", &pThisCC->hLinkUpTimer); 2218 2247 AssertRCReturn(rc, rc); 2219 2248 2220 2249 #ifdef VNET_TX_DELAY 2221 2250 /* Create Transmit Delay Timer */ 2222 rc = PDMDevHlpT MTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vnetR3TxTimer, pThis, TMTIMER_FLAGS_NO_CRIT_SECT,2223 "VirtioNet TX Delay Timer", &pThis->pTxTimerR3);2251 rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vnetR3TxTimer, pThis, TMTIMER_FLAGS_NO_CRIT_SECT, 2252 "VirtioNet TX Delay Timer", &pThis->hTxTimer); 2224 2253 AssertRCReturn(rc, rc); 2225 pThis->pTxTimerR0 = TMTimerR0Ptr(pThis->pTxTimerR3);2226 pThis->pTxTimerRC = TMTimerRCPtr(pThis->pTxTimerR3);2227 2254 2228 2255 pThis->u32i = pThis->u32AvgDiff = pThis->u32MaxDiff = 0; … … 2230 2257 #endif /* VNET_TX_DELAY */ 2231 2258 2232 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis ->VPCI.IBase, &pThis->pDrvBase, "Network Port");2259 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThisCC->VPCI.IBase, &pThisCC->pDrvBase, "Network Port"); 2233 2260 if (RT_SUCCESS(rc)) 2234 2261 { … … 2238 2265 N_("A Domain Name Server (DNS) for NAT networking could not be determined. Ensure that your host is correctly connected to an ISP. If you ignore this warning the guest will not be able to perform nameserver lookups and it will probably observe delays if trying so")); 2239 2266 } 2240 pThis ->pDrv = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMINETWORKUP);2241 AssertMsgReturn(pThis ->pDrv, ("Failed to obtain the PDMINETWORKUP interface!\n"),2267 pThisCC->pDrv = PDMIBASE_QUERY_INTERFACE(pThisCC->pDrvBase, PDMINETWORKUP); 2268 AssertMsgReturn(pThisCC->pDrv, ("Failed to obtain the PDMINETWORKUP interface!\n"), 2242 2269 VERR_PDM_MISSING_INTERFACE_BELOW); 2243 2270 2244 vnetR3CreateTxThreadAndEvent(pDevIns, pThis );2271 vnetR3CreateTxThreadAndEvent(pDevIns, pThis, pThisCC); 2245 2272 } 2246 2273 else if ( rc == VERR_PDM_NO_ATTACHED_DRIVER … … 2256 2283 AssertRCReturn(rc, rc); 2257 2284 2258 rc = vnetIoCb_Reset(&pThis->VPCI); 2285 ASMCompilerBarrier(); /* paranoia */ 2286 rc = vnetIoCb_Reset(pDevIns); 2259 2287 AssertRCReturn(rc, rc); 2260 2288 2289 /* 2290 * Statistics and debug stuff. 2291 */ 2261 2292 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data received", "/Public/Net/VNet%u/BytesReceived", iInstance); 2262 2293 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data transmitted", "/Public/Net/VNet%u/BytesTransmitted", iInstance); … … 2279 2310 # endif 2280 2311 2312 char szInfo[16]; 2313 RTStrPrintf(szInfo, sizeof(szInfo), pDevIns->iInstance ? "vionet%u" : "vionet", pDevIns->iInstance); 2314 PDMDevHlpDBGFInfoRegisterArgv(pDevIns, szInfo, "virtio-net info", vnetR3Info); 2315 2281 2316 return VINF_SUCCESS; 2282 2317 } 2283 2318 2284 #endif /* IN_RING3 */ 2319 #else /* !IN_RING3 */ 2320 2321 /** 2322 * @callback_method_impl{PDMDEVREGR0,pfnConstruct} 2323 */ 2324 static DECLCALLBACK(int) vnetRZConstruct(PPDMDEVINS pDevIns) 2325 { 2326 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 2327 PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE); 2328 PVNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC); 2329 2330 int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns)); 2331 AssertRCReturn(rc, rc); 2332 2333 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->hIoPorts, vnetIOPortOut, vnetIOPortIn, NULL /*pvUser*/); 2334 AssertRCReturn(rc, rc); 2335 2336 return vpciRZInit(pDevIns, &pThis->VPCI, &pThisCC->VPCI); 2337 } 2338 2339 #endif /* !IN_RING3 */ 2285 2340 2286 2341 /** … … 2292 2347 /* .uReserved0 = */ 0, 2293 2348 /* .szName = */ "virtio-net", 2294 #ifdef VNET_GC_SUPPORT 2295 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ, 2296 #else 2297 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS, 2298 #endif 2349 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE, 2299 2350 /* .fClass = */ PDM_DEVREG_CLASS_NETWORK, 2300 2351 /* .cMaxInstances = */ ~0U, 2301 2352 /* .uSharedVersion = */ 42, 2302 2353 /* .cbInstanceShared = */ sizeof(VNETSTATE), 2303 /* .cbInstanceCC = */ 0,2304 /* .cbInstanceRC = */ 0,2354 /* .cbInstanceCC = */ sizeof(VNETSTATECC), 2355 /* .cbInstanceRC = */ sizeof(VNETSTATERC), 2305 2356 /* .cMaxPciDevices = */ 1, 2306 2357 /* .cMaxMsixVectors = */ 0, … … 2311 2362 /* .pfnConstruct = */ vnetR3Construct, 2312 2363 /* .pfnDestruct = */ vnetR3Destruct, 2313 /* .pfnRelocate = */ vnetR3Relocate,2364 /* .pfnRelocate = */ NULL, 2314 2365 /* .pfnMemSetup = */ NULL, 2315 2366 /* .pfnPowerOn = */ NULL, … … 2333 2384 #elif defined(IN_RING0) 2334 2385 /* .pfnEarlyConstruct = */ NULL, 2335 /* .pfnConstruct = */ NULL,2386 /* .pfnConstruct = */ vnetRZConstruct, 2336 2387 /* .pfnDestruct = */ NULL, 2337 2388 /* .pfnFinalDestruct = */ NULL, … … 2346 2397 /* .pfnReserved7 = */ NULL, 2347 2398 #elif defined(IN_RC) 2348 /* .pfnConstruct = */ NULL,2399 /* .pfnConstruct = */ vnetRZConstruct, 2349 2400 /* .pfnReserved0 = */ NULL, 2350 2401 /* .pfnReserved1 = */ NULL, -
trunk/src/VBox/Devices/VirtIO/Virtio.cpp
r81703 r81720 25 25 #include <iprt/uuid.h> 26 26 #include <VBox/vmm/pdmdev.h> 27 #include <VBox/AssertGuest.h> 27 28 #include "Virtio.h" 28 29 29 #define INSTANCE(pState) pState->szInstance 30 #define IFACE_TO_STATE(pIface, ifaceName) ((VPCISTATE *)((char*)(pIface) - RT_UOFFSETOF(VPCISTATE, ifaceName))) 31 32 #ifdef LOG_ENABLED 33 # define QUEUENAME(s, q) (q->pcszName) 34 #endif 35 36 37 38 #ifndef VBOX_DEVICE_STRUCT_TESTCASE 39 40 //RT_C_DECLS_BEGIN 41 //RT_C_DECLS_END 30 31 /********************************************************************************************************************************* 32 * Defined Constants And Macros * 33 *********************************************************************************************************************************/ 34 #define INSTANCE(pThis) (pThis->szInstance) 42 35 43 36 … … 68 61 // } 69 62 70 void vringReadDesc(P VPCISTATE pState, PVRING pVRing, uint32_t uIndex, PVRINGDESC pDesc)71 { 72 //Log(("%s vringReadDesc: ring=%p idx=%u\n", INSTANCE(p State), pVRing, uIndex));73 PDMDevHlpPhysRead(p State->CTX_SUFF(pDevIns),63 void vringReadDesc(PPDMDEVINS pDevIns, PVRING pVRing, uint32_t uIndex, PVRINGDESC pDesc) 64 { 65 //Log(("%s vringReadDesc: ring=%p idx=%u\n", INSTANCE(pThis), pVRing, uIndex)); 66 PDMDevHlpPhysRead(pDevIns, 74 67 pVRing->addrDescriptors + sizeof(VRINGDESC) * (uIndex % pVRing->uSize), 75 68 pDesc, sizeof(VRINGDESC)); 76 } 77 78 uint16_t vringReadAvail(PVPCISTATE pState, PVRING pVRing, uint32_t uIndex) 79 { 80 uint16_t tmp; 81 82 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns),83 69 /** @todo r=bird: Why exactly are we sometimes using PDMDevHlpPhysRead rather 70 * than PDMDevHlpPCIPhysRead? */ 71 } 72 73 uint16_t vringReadAvail(PPDMDEVINS pDevIns, PVRING pVRing, uint32_t uIndex) 74 { 75 uint16_t tmp = 0; 76 PDMDevHlpPhysRead(pDevIns, pVRing->addrAvail + RT_UOFFSETOF_DYN(VRINGAVAIL, auRing[uIndex % pVRing->uSize]), 84 77 &tmp, sizeof(tmp)); 85 78 return tmp; 86 79 } 87 80 88 uint16_t vringReadAvailFlags(PVPCISTATE pState, PVRING pVRing) 89 { 90 uint16_t tmp; 91 92 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 93 pVRing->addrAvail + RT_UOFFSETOF(VRINGAVAIL, uFlags), 94 &tmp, sizeof(tmp)); 81 uint16_t vringReadAvailFlags(PPDMDEVINS pDevIns, PVRING pVRing) 82 { 83 uint16_t tmp = 0; 84 PDMDevHlpPhysRead(pDevIns, pVRing->addrAvail + RT_UOFFSETOF(VRINGAVAIL, uFlags), &tmp, sizeof(tmp)); 95 85 return tmp; 96 86 } 97 87 98 void vringSetNotification(PVPCISTATE pState, PVRING pVRing, bool fEnabled) 99 { 100 uint16_t tmp; 101 102 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 103 pVRing->addrUsed + RT_UOFFSETOF(VRINGUSED, uFlags), 104 &tmp, sizeof(tmp)); 88 void vringSetNotification(PPDMDEVINS pDevIns, PVRING pVRing, bool fEnabled) 89 { 90 uint16_t fState = 0; 91 PDMDevHlpPhysRead(pDevIns, pVRing->addrUsed + RT_UOFFSETOF(VRINGUSED, uFlags), &fState, sizeof(fState)); 105 92 106 93 if (fEnabled) 107 tmp&= ~ VRINGUSED_F_NO_NOTIFY;94 fState &= ~ VRINGUSED_F_NO_NOTIFY; 108 95 else 109 tmp |= VRINGUSED_F_NO_NOTIFY; 110 111 PDMDevHlpPCIPhysWrite(pState->CTX_SUFF(pDevIns), 112 pVRing->addrUsed + RT_UOFFSETOF(VRINGUSED, uFlags), 113 &tmp, sizeof(tmp)); 114 } 115 116 bool vqueueSkip(PVPCISTATE pState, PVQUEUE pQueue) 117 { 118 if (vqueueIsEmpty(pState, pQueue)) 96 fState |= VRINGUSED_F_NO_NOTIFY; 97 98 PDMDevHlpPCIPhysWrite(pDevIns, pVRing->addrUsed + RT_UOFFSETOF(VRINGUSED, uFlags), &fState, sizeof(fState)); 99 } 100 101 bool vqueueSkip(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue) 102 { 103 if (vqueueIsEmpty(pDevIns, pQueue)) 119 104 return false; 120 105 121 Log2(("%s vqueueSkip: %s avail_idx=%u\n", INSTANCE(pState), 122 QUEUENAME(pState, pQueue), pQueue->uNextAvailIndex)); 106 Log2(("%s vqueueSkip: %s avail_idx=%u\n", INSTANCE(pThis), pQueue->szName, pQueue->uNextAvailIndex)); 123 107 pQueue->uNextAvailIndex++; 124 108 return true; 125 109 } 126 110 127 bool vqueueGet(P VPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove)128 { 129 if (vqueueIsEmpty(p State, pQueue))111 bool vqueueGet(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove) 112 { 113 if (vqueueIsEmpty(pDevIns, pQueue)) 130 114 return false; 131 115 132 116 pElem->nIn = pElem->nOut = 0; 133 117 134 Log2(("%s vqueueGet: %s avail_idx=%u\n", INSTANCE(pState), 135 QUEUENAME(pState, pQueue), pQueue->uNextAvailIndex)); 118 Log2(("%s vqueueGet: %s avail_idx=%u\n", INSTANCE(pThis), pQueue->szName, pQueue->uNextAvailIndex)); 136 119 137 120 VRINGDESC desc; 138 uint16_t idx = vringReadAvail(p State, &pQueue->VRing, pQueue->uNextAvailIndex);121 uint16_t idx = vringReadAvail(pDevIns, &pQueue->VRing, pQueue->uNextAvailIndex); 139 122 if (fRemove) 140 123 pQueue->uNextAvailIndex++; … … 157 140 { 158 141 LogRel(("%s: too many linked descriptors; check if the guest arranges descriptors in a loop.\n", 159 INSTANCE(p State)));142 INSTANCE(pThis))); 160 143 if (ASMAtomicReadU32(&s_cMessages) != 1) 161 144 LogRel(("%s: (the above error has occured %u times so far)\n", 162 INSTANCE(p State), ASMAtomicReadU32(&s_cMessages)));145 INSTANCE(pThis), ASMAtomicReadU32(&s_cMessages))); 163 146 ASMAtomicWriteU32(&s_cThreshold, ASMAtomicReadU32(&s_cThreshold) * 10); 164 147 } … … 167 150 RT_UNTRUSTED_VALIDATED_FENCE(); 168 151 169 vringReadDesc(p State, &pQueue->VRing, idx, &desc);152 vringReadDesc(pDevIns, &pQueue->VRing, idx, &desc); 170 153 if (desc.u16Flags & VRINGDESC_F_WRITE) 171 154 { 172 Log2(("%s vqueueGet: %s IN seg=%u desc_idx=%u addr=%p cb=%u\n", INSTANCE(p State),173 QUEUENAME(pState, pQueue), pElem->nIn, idx, desc.u64Addr, desc.uLen));155 Log2(("%s vqueueGet: %s IN seg=%u desc_idx=%u addr=%p cb=%u\n", INSTANCE(pThis), 156 pQueue->szName, pElem->nIn, idx, desc.u64Addr, desc.uLen)); 174 157 pSeg = &pElem->aSegsIn[pElem->nIn++]; 175 158 } 176 159 else 177 160 { 178 Log2(("%s vqueueGet: %s OUT seg=%u desc_idx=%u addr=%p cb=%u\n", INSTANCE(p State),179 QUEUENAME(pState, pQueue), pElem->nOut, idx, desc.u64Addr, desc.uLen));161 Log2(("%s vqueueGet: %s OUT seg=%u desc_idx=%u addr=%p cb=%u\n", INSTANCE(pThis), 162 pQueue->szName, pElem->nOut, idx, desc.u64Addr, desc.uLen)); 180 163 pSeg = &pElem->aSegsOut[pElem->nOut++]; 181 164 } … … 188 171 } while (desc.u16Flags & VRINGDESC_F_NEXT); 189 172 190 Log2(("%s vqueueGet: %s head_desc_idx=%u nIn=%u nOut=%u\n", INSTANCE(p State),191 QUEUENAME(pState, pQueue), pElem->uIndex, pElem->nIn, pElem->nOut));173 Log2(("%s vqueueGet: %s head_desc_idx=%u nIn=%u nOut=%u\n", INSTANCE(pThis), 174 pQueue->szName, pElem->uIndex, pElem->nIn, pElem->nOut)); 192 175 return true; 193 176 } 194 177 195 uint16_t vringReadUsedIndex(PVPCISTATE pState, PVRING pVRing) 196 { 197 uint16_t tmp; 198 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 199 pVRing->addrUsed + RT_UOFFSETOF(VRINGUSED, uIndex), 200 &tmp, sizeof(tmp)); 178 #ifdef LOG_ENABLED 179 static uint16_t vringReadUsedIndex(PPDMDEVINS pDevIns, PVRING pVRing) 180 { 181 uint16_t tmp = 0; 182 PDMDevHlpPhysRead(pDevIns, pVRing->addrUsed + RT_UOFFSETOF(VRINGUSED, uIndex), &tmp, sizeof(tmp)); 201 183 return tmp; 202 184 } 203 204 void vringWriteUsedIndex(PVPCISTATE pState, PVRING pVRing, uint16_t u16Value) 205 { 206 PDMDevHlpPCIPhysWrite(pState->CTX_SUFF(pDevIns), 185 #endif 186 187 static void vringWriteUsedIndex(PPDMDEVINS pDevIns, PVRING pVRing, uint16_t u16Value) 188 { 189 PDMDevHlpPCIPhysWrite(pDevIns, 207 190 pVRing->addrUsed + RT_UOFFSETOF(VRINGUSED, uIndex), 208 191 &u16Value, sizeof(u16Value)); 209 192 } 210 193 211 void vringWriteUsedElem(PVPCISTATE pState, PVRING pVRing, uint32_t uIndex, uint32_t uId, uint32_t uLen)194 static void vringWriteUsedElem(PPDMDEVINS pDevIns, PVRING pVRing, uint32_t uIndex, uint32_t uId, uint32_t uLen) 212 195 { 213 196 VRINGUSEDELEM elem; … … 215 198 elem.uId = uId; 216 199 elem.uLen = uLen; 217 PDMDevHlpPCIPhysWrite(p State->CTX_SUFF(pDevIns),200 PDMDevHlpPCIPhysWrite(pDevIns, 218 201 pVRing->addrUsed + RT_UOFFSETOF_DYN(VRINGUSED, aRing[uIndex % pVRing->uSize]), 219 202 &elem, sizeof(elem)); … … 221 204 222 205 223 void vqueuePut(PVPCISTATE pState, PVQUEUE pQueue, 224 PVQUEUEELEM pElem, uint32_t uTotalLen, uint32_t uReserved) 225 { 226 Log2(("%s vqueuePut: %s" 227 " desc_idx=%u acb=%u (%u)\n", 228 INSTANCE(pState), QUEUENAME(pState, pQueue), 229 pElem->uIndex, uTotalLen, uReserved)); 206 void vqueuePut(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t uTotalLen, uint32_t uReserved) 207 { 208 Log2(("%s vqueuePut: %s desc_idx=%u acb=%u (%u)\n", INSTANCE(pThis), pQueue->szName, pElem->uIndex, uTotalLen, uReserved)); 230 209 231 210 Assert(uReserved < uTotalLen); … … 252 231 if (pElem->aSegsIn[i].pv != NULL) 253 232 { 254 Log2(("%s vqueuePut: %s" 255 " used_idx=%u seg=%u addr=%p pv=%p cb=%u acb=%u\n", 256 INSTANCE(pState), QUEUENAME(pState, pQueue), 257 pQueue->uNextUsedIndex, i, 258 (void *)pElem->aSegsIn[i].addr, pElem->aSegsIn[i].pv, 259 pElem->aSegsIn[i].cb, cbSegLen)); 260 261 PDMDevHlpPCIPhysWrite(pState->CTX_SUFF(pDevIns), 233 Log2(("%s vqueuePut: %s used_idx=%u seg=%u addr=%RGp pv=%p cb=%u acb=%u\n", INSTANCE(pThis), pQueue->szName, 234 pQueue->uNextUsedIndex, i, pElem->aSegsIn[i].addr, pElem->aSegsIn[i].pv, pElem->aSegsIn[i].cb, cbSegLen)); 235 236 PDMDevHlpPCIPhysWrite(pDevIns, 262 237 pElem->aSegsIn[i].addr + cbSkip, 263 238 pElem->aSegsIn[i].pv, … … 269 244 } 270 245 271 Log2(("%s vqueuePut: %s" 272 " used_idx=%u guest_used_idx=%u id=%u len=%u\n", 273 INSTANCE(pState), QUEUENAME(pState, pQueue), 274 pQueue->uNextUsedIndex, vringReadUsedIndex(pState, &pQueue->VRing), 275 pElem->uIndex, uTotalLen)); 276 277 vringWriteUsedElem(pState, &pQueue->VRing, 246 Log2(("%s vqueuePut: %s used_idx=%u guest_used_idx=%u id=%u len=%u\n", INSTANCE(pThis), pQueue->szName, 247 pQueue->uNextUsedIndex, vringReadUsedIndex(pDevIns, &pQueue->VRing), pElem->uIndex, uTotalLen)); 248 249 vringWriteUsedElem(pDevIns, &pQueue->VRing, 278 250 pQueue->uNextUsedIndex++, 279 251 pElem->uIndex, uTotalLen); … … 281 253 282 254 283 void vqueueNotify(PVPCISTATE pState, PVQUEUE pQueue) 284 { 285 LogFlow(("%s vqueueNotify: %s availFlags=%x guestFeatures=%x vqueue is %sempty\n", 286 INSTANCE(pState), QUEUENAME(pState, pQueue), 287 vringReadAvailFlags(pState, &pQueue->VRing), 288 pState->uGuestFeatures, vqueueIsEmpty(pState, pQueue)?"":"not ")); 289 if (!(vringReadAvailFlags(pState, &pQueue->VRing) & VRINGAVAIL_F_NO_INTERRUPT) 290 || ((pState->uGuestFeatures & VPCI_F_NOTIFY_ON_EMPTY) && vqueueIsEmpty(pState, pQueue))) 291 { 292 int rc = vpciRaiseInterrupt(pState, VERR_INTERNAL_ERROR, VPCI_ISR_QUEUE); 255 void vqueueNotify(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue) 256 { 257 uint16_t const fAvail = vringReadAvailFlags(pDevIns, &pQueue->VRing); 258 LogFlow(("%s vqueueNotify: %s availFlags=%x guestFeatures=%x vqueue is %sempty\n", INSTANCE(pThis), pQueue->szName, 259 fAvail, pThis->uGuestFeatures, vqueueIsEmpty(pDevIns, pQueue)?"":"not ")); 260 if ( !(fAvail & VRINGAVAIL_F_NO_INTERRUPT) 261 || ((pThis->uGuestFeatures & VPCI_F_NOTIFY_ON_EMPTY) && vqueueIsEmpty(pDevIns, pQueue))) 262 { 263 int rc = vpciRaiseInterrupt(pDevIns, pThis, VERR_INTERNAL_ERROR, VPCI_ISR_QUEUE); 293 264 if (RT_FAILURE(rc)) 294 Log(("%s vqueueNotify: Failed to raise an interrupt (%Rrc).\n", INSTANCE(p State), rc));265 Log(("%s vqueueNotify: Failed to raise an interrupt (%Rrc).\n", INSTANCE(pThis), rc)); 295 266 } 296 267 else 297 { 298 STAM_COUNTER_INC(&pState->StatIntsSkipped); 299 } 300 301 } 302 303 void vqueueSync(PVPCISTATE pState, PVQUEUE pQueue) 304 { 305 Log2(("%s vqueueSync: %s old_used_idx=%u new_used_idx=%u\n", INSTANCE(pState), 306 QUEUENAME(pState, pQueue), vringReadUsedIndex(pState, &pQueue->VRing), pQueue->uNextUsedIndex)); 307 vringWriteUsedIndex(pState, &pQueue->VRing, pQueue->uNextUsedIndex); 308 vqueueNotify(pState, pQueue); 268 STAM_COUNTER_INC(&pThis->StatIntsSkipped); 269 270 } 271 272 void vqueueSync(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue) 273 { 274 Log2(("%s vqueueSync: %s old_used_idx=%u new_used_idx=%u\n", INSTANCE(pThis), 275 pQueue->szName, vringReadUsedIndex(pDevIns, &pQueue->VRing), pQueue->uNextUsedIndex)); 276 vringWriteUsedIndex(pDevIns, &pQueue->VRing, pQueue->uNextUsedIndex); 277 vqueueNotify(pDevIns, pThis, pQueue); 309 278 } 310 279 … … 313 282 * Raise interrupt. 314 283 * 315 * @param pState The device state structure. 284 * @param pDevIns The device instance. 285 * @param pThis The shared virtio core instance data. 316 286 * @param rcBusy Status code to return when the critical section is busy. 317 287 * @param u8IntCause Interrupt cause bit mask to set in PCI ISR port. 318 288 */ 319 int vpciRaiseInterrupt( VPCISTATE *pState, int rcBusy, uint8_t u8IntCause)289 int vpciRaiseInterrupt(PPDMDEVINS pDevIns, PVPCISTATE pThis, int rcBusy, uint8_t u8IntCause) 320 290 { 321 291 RT_NOREF_PV(rcBusy); 322 // int rc = vpciCsEnter(p State, rcBusy);292 // int rc = vpciCsEnter(pThis, rcBusy); 323 293 // if (RT_UNLIKELY(rc != VINF_SUCCESS)) 324 294 // return rc; 325 295 326 STAM_COUNTER_INC(&pState->StatIntsRaised); 327 LogFlow(("%s vpciRaiseInterrupt: u8IntCause=%x\n", 328 INSTANCE(pState), u8IntCause)); 329 330 pState->uISR |= u8IntCause; 331 PDMDevHlpPCISetIrq(pState->CTX_SUFF(pDevIns), 0, 1); 332 // vpciCsLeave(pState); 296 STAM_COUNTER_INC(&pThis->StatIntsRaised); 297 LogFlow(("%s vpciRaiseInterrupt: u8IntCause=%x\n", INSTANCE(pThis), u8IntCause)); 298 299 pThis->uISR |= u8IntCause; 300 PDMDevHlpPCISetIrq(pDevIns, 0, 1); 301 // vpciCsLeave(pThis); 333 302 return VINF_SUCCESS; 334 303 } … … 337 306 * Lower interrupt. 338 307 * 339 * @param pState The device state structure. 340 */ 341 static void vpciLowerInterrupt(VPCISTATE *pState) 342 { 343 LogFlow(("%s vpciLowerInterrupt\n", INSTANCE(pState))); 344 PDMDevHlpPCISetIrq(pState->CTX_SUFF(pDevIns), 0, 0); 345 } 346 347 348 void vpciReset(PVPCISTATE pState) 308 * @param pDevIns The device instance. 309 * @param pThis The shared virtio core instance data. 310 */ 311 static void vpciLowerInterrupt(PPDMDEVINS pDevIns, PVPCISTATE pThis) 312 { 313 LogFlow(("%s vpciLowerInterrupt\n", INSTANCE(pThis))); 314 RT_NOREF(pThis); 315 PDMDevHlpPCISetIrq(pDevIns, 0, 0); 316 } 317 318 319 void vpciReset(PPDMDEVINS pDevIns, PVPCISTATE pThis) 349 320 { 350 321 /* No interrupts should survive device reset, see @bugref(9556). */ 351 if (p State->uISR)352 vpciLowerInterrupt(p State);353 354 p State->uGuestFeatures = 0;355 p State->uQueueSelector = 0;356 p State->uStatus = 0;357 p State->uISR = 0;358 359 for (unsigned i = 0; i < p State->nQueues; i++)360 vqueueReset(&p State->Queues[i]);361 } 362 363 364 DECLINLINE(uint32_t) vpciGetHostFeatures(PVPCISTATE p State, PCVPCIIOCALLBACKS pCallbacks)365 { 366 return pCallbacks->pfnGetHostFeatures(p State)322 if (pThis->uISR) 323 vpciLowerInterrupt(pDevIns, pThis); 324 325 pThis->uGuestFeatures = 0; 326 pThis->uQueueSelector = 0; 327 pThis->uStatus = 0; 328 pThis->uISR = 0; 329 330 for (unsigned i = 0; i < pThis->cQueues; i++) 331 vqueueReset(&pThis->Queues[i]); 332 } 333 334 335 DECLINLINE(uint32_t) vpciGetHostFeatures(PVPCISTATE pThis, PCVPCIIOCALLBACKS pCallbacks) 336 { 337 return pCallbacks->pfnGetHostFeatures(pThis) 367 338 | VPCI_F_NOTIFY_ON_EMPTY; 368 339 } … … 374 345 * 375 346 * @param pDevIns The device instance. 376 * @param p State The VPCI core state.377 * @param Port Port number used for the IN operation.347 * @param pThis The shared virtio core instance data. 348 * @param offPort The offset into the I/O range of the port being read. 378 349 * @param pu32 Where to store the result. 379 350 * @param cb Number of bytes read. … … 382 353 */ 383 354 int vpciIOPortIn(PPDMDEVINS pDevIns, 384 PVPCISTATE p State,385 RTIOPORT Port,355 PVPCISTATE pThis, 356 RTIOPORT offPort, 386 357 uint32_t *pu32, 387 358 unsigned cb, 388 359 PCVPCIIOCALLBACKS pCallbacks) 389 360 { 390 STAM_PROFILE_ADV_START(&pState->CTX_SUFF(StatIORead), a); 391 int rc = VINF_SUCCESS; 361 STAM_PROFILE_ADV_START(&pThis->CTX_SUFF(StatIORead), a); 392 362 393 363 /* … … 400 370 * holding cs transmitting queued packets. 401 371 * 402 rc = vpciCsEnter(pState, VINF_IOM_R3_IOPORT_READ);372 int rc = vpciCsEnter(pThis, VINF_IOM_R3_IOPORT_READ); 403 373 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 404 374 { 405 STAM_PROFILE_ADV_STOP(&p State->CTX_SUFF(StatIORead), a);375 STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF(StatIORead), a); 406 376 return rc; 407 377 }*/ 408 409 Port -= pState->IOPortBase; 410 switch ( Port)378 int rc = VINF_SUCCESS; 379 380 switch (offPort) 411 381 { 412 382 case VPCI_HOST_FEATURES: 413 383 /* Tell the guest what features we support. */ 414 *pu32 = vpciGetHostFeatures(pState, pCallbacks) | VPCI_F_BAD_FEATURE; 384 ASSERT_GUEST_MSG(cb == 4, ("%d\n", cb)); 385 *pu32 = vpciGetHostFeatures(pThis, pCallbacks) | VPCI_F_BAD_FEATURE; 415 386 break; 416 387 417 388 case VPCI_GUEST_FEATURES: 418 *pu32 = pState->uGuestFeatures; 389 ASSERT_GUEST_MSG(cb == 4, ("%d\n", cb)); 390 *pu32 = pThis->uGuestFeatures; 419 391 break; 420 392 421 393 case VPCI_QUEUE_PFN: 422 *pu32 = pState->Queues[pState->uQueueSelector].uPageNumber; 394 ASSERT_GUEST_MSG(cb == 4, ("%d\n", cb)); 395 *pu32 = pThis->Queues[pThis->uQueueSelector].uPageNumber; 423 396 break; 424 397 425 398 case VPCI_QUEUE_NUM: 426 A ssert(cb == 2);427 * (uint16_t*)pu32 = pState->Queues[pState->uQueueSelector].VRing.uSize;399 ASSERT_GUEST_MSG(cb == 2, ("%d\n", cb)); 400 *pu32 = pThis->Queues[pThis->uQueueSelector].VRing.uSize; 428 401 break; 429 402 430 403 case VPCI_QUEUE_SEL: 431 A ssert(cb == 2);432 * (uint16_t*)pu32 = pState->uQueueSelector;404 ASSERT_GUEST_MSG(cb == 2, ("%d\n", cb)); 405 *pu32 = pThis->uQueueSelector; 433 406 break; 434 407 435 408 case VPCI_STATUS: 436 A ssert(cb == 1);437 * (uint8_t*)pu32 = pState->uStatus;409 ASSERT_GUEST_MSG(cb == 1, ("%d\n", cb)); 410 *pu32 = pThis->uStatus; 438 411 break; 439 412 440 413 case VPCI_ISR: 441 A ssert(cb == 1);442 * (uint8_t*)pu32 = pState->uISR;443 p State->uISR = 0; /* read clears all interrupts */444 vpciLowerInterrupt(p State);414 ASSERT_GUEST_MSG(cb == 1, ("%d\n", cb)); 415 *pu32 = pThis->uISR; 416 pThis->uISR = 0; /* read clears all interrupts */ 417 vpciLowerInterrupt(pDevIns, pThis); 445 418 break; 446 419 447 420 default: 448 if ( Port >= VPCI_CONFIG)449 rc = pCallbacks->pfnGetConfig(p State,Port - VPCI_CONFIG, cb, pu32);421 if (offPort >= VPCI_CONFIG) 422 rc = pCallbacks->pfnGetConfig(pThis, offPort - VPCI_CONFIG, cb, pu32); 450 423 else 451 424 { 452 *pu32 = 0xFFFFFFFF;425 *pu32 = UINT32_MAX; 453 426 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "%s vpciIOPortIn: no valid port at offset port=%RTiop cb=%08x\n", 454 INSTANCE(p State),Port, cb);427 INSTANCE(pThis), offPort, cb); 455 428 } 456 429 break; 457 430 } 458 Log3(("%s vpciIOPortIn: At %RTiop in %0*x\n", INSTANCE(pState), Port, cb*2, *pu32)); 459 STAM_PROFILE_ADV_STOP(&pState->CTX_SUFF(StatIORead), a); 460 //vpciCsLeave(pState); 431 Log3(("%s vpciIOPortIn: At %RTiop in %0*x\n", INSTANCE(pThis), offPort, cb*2, *pu32)); 432 433 //vpciCsLeave(pThis); 434 435 STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF(StatIORead), a); 461 436 return rc; 462 437 } … … 469 444 * 470 445 * @param pDevIns The device instance. 471 * @param p State The VPCI core state.472 * @param Port Port number used for the IN operation.446 * @param pThis The shared virtio core instance data. 447 * @param offPort The offset into the I/O range of the port being written. 473 448 * @param u32 The value to output. 474 449 * @param cb The value size in bytes. … … 477 452 */ 478 453 int vpciIOPortOut(PPDMDEVINS pDevIns, 479 PVPCISTATE pState, 480 RTIOPORT Port, 454 PVPCISTATE pThis, 455 PVPCISTATECC pThisCC, 456 RTIOPORT offPort, 481 457 uint32_t u32, 482 458 unsigned cb, 483 459 PCVPCIIOCALLBACKS pCallbacks) 484 460 { 485 STAM_PROFILE_ADV_START(&p State->CTX_SUFF(StatIOWrite), a);461 STAM_PROFILE_ADV_START(&pThis->CTX_SUFF(StatIOWrite), a); 486 462 int rc = VINF_SUCCESS; 487 463 bool fHasBecomeReady; 488 464 489 Port -= pState->IOPortBase; 490 Log3(("%s virtioIOPortOut: At %RTiop out %0*x\n", INSTANCE(pState), Port, cb*2, u32)); 491 492 switch (Port) 465 Log3(("%s virtioIOPortOut: At offPort=%RTiop out %0*x\n", INSTANCE(pThis), offPort, cb*2, u32)); 466 467 switch (offPort) 493 468 { 494 469 case VPCI_GUEST_FEATURES: 495 470 { 496 const uint32_t fHostFeatures = vpciGetHostFeatures(p State, pCallbacks);471 const uint32_t fHostFeatures = vpciGetHostFeatures(pThis, pCallbacks); 497 472 498 473 if (RT_LIKELY((u32 & ~fHostFeatures) == 0)) 499 { 500 pState->uGuestFeatures = u32; 501 } 474 pThis->uGuestFeatures = u32; 502 475 else 503 476 { … … 510 483 { 511 484 Log(("%s WARNING! Guest failed to negotiate properly (guest=%x)\n", 512 INSTANCE(p State), u32));513 p State->uGuestFeatures = pCallbacks->pfnGetHostMinimalFeatures(pState);485 INSTANCE(pThis), u32)); 486 pThis->uGuestFeatures = pCallbacks->pfnGetHostMinimalFeatures(pThis); 514 487 } 515 488 else 516 489 { 517 490 Log(("%s Guest asked for features host does not support! (host=%x guest=%x)\n", 518 INSTANCE(p State), fHostFeatures, u32));519 p State->uGuestFeatures = u32 & fHostFeatures;491 INSTANCE(pThis), fHostFeatures, u32)); 492 pThis->uGuestFeatures = u32 & fHostFeatures; 520 493 } 521 494 } 522 pCallbacks->pfnSetHostFeatures(p State, pState->uGuestFeatures);495 pCallbacks->pfnSetHostFeatures(pThis, pThis->uGuestFeatures); 523 496 break; 524 497 } … … 531 504 * VIRTIO_PCI_QUEUE_NUM. 532 505 */ 533 p State->Queues[pState->uQueueSelector].uPageNumber = u32;506 pThis->Queues[pThis->uQueueSelector].uPageNumber = u32; 534 507 if (u32) 535 vqueueInit(&p State->Queues[pState->uQueueSelector], u32);508 vqueueInit(&pThis->Queues[pThis->uQueueSelector], u32); 536 509 else 537 rc = pCallbacks->pfnReset(p State);510 rc = pCallbacks->pfnReset(pDevIns); 538 511 break; 539 512 540 513 case VPCI_QUEUE_SEL: 541 A ssert(cb == 2);514 ASSERT_GUEST_MSG(cb == 2, ("cb=%u\n", cb)); 542 515 u32 &= 0xFFFF; 543 if (u32 < p State->nQueues)544 p State->uQueueSelector = u32;516 if (u32 < pThis->cQueues) 517 pThis->uQueueSelector = u32; 545 518 else 546 Log3(("%s vpciIOPortOut: Invalid queue selector %08x\n", INSTANCE(p State), u32));519 Log3(("%s vpciIOPortOut: Invalid queue selector %08x\n", INSTANCE(pThis), u32)); 547 520 break; 548 521 549 522 case VPCI_QUEUE_NOTIFY: 550 523 #ifdef IN_RING3 551 A ssert(cb == 2);524 ASSERT_GUEST_MSG(cb == 2, ("cb=%u\n", cb)); 552 525 u32 &= 0xFFFF; 553 if (u32 < p State->nQueues)526 if (u32 < pThis->cQueues) 554 527 { 555 528 RT_UNTRUSTED_VALIDATED_FENCE(); 556 if (p State->Queues[u32].VRing.addrDescriptors)529 if (pThis->Queues[u32].VRing.addrDescriptors) 557 530 { 558 // rc = vpciCsEnter(pState, VERR_SEM_BUSY); 531 532 // rc = vpciCsEnter(pThis, VERR_SEM_BUSY); 559 533 // if (RT_LIKELY(rc == VINF_SUCCESS)) 560 534 // { 561 p State->Queues[u32].pfnCallback(pDevIns, pState, &pState->Queues[u32]);562 // vpciCsLeave(p State);535 pThisCC->Queues[u32].pfnCallback(pDevIns, &pThis->Queues[u32]); 536 // vpciCsLeave(pThis); 563 537 // } 564 538 } 565 539 else 566 540 Log(("%s The queue (#%d) being notified has not been initialized.\n", 567 INSTANCE(p State), u32));541 INSTANCE(pThis), u32)); 568 542 } 569 543 else 570 Log(("%s Invalid queue number (%d)\n", INSTANCE(p State), u32));544 Log(("%s Invalid queue number (%d)\n", INSTANCE(pThis), u32)); 571 545 #else 546 RT_NOREF(pThisCC); 572 547 rc = VINF_IOM_R3_IOPORT_WRITE; 573 548 #endif … … 575 550 576 551 case VPCI_STATUS: 577 A ssert(cb == 1);552 ASSERT_GUEST_MSG(cb == 1, ("cb=%u\n", cb)); 578 553 u32 &= 0xFF; 579 fHasBecomeReady = !(p State->uStatus & VPCI_STATUS_DRV_OK) && (u32 & VPCI_STATUS_DRV_OK);580 p State->uStatus = u32;554 fHasBecomeReady = !(pThis->uStatus & VPCI_STATUS_DRV_OK) && (u32 & VPCI_STATUS_DRV_OK); 555 pThis->uStatus = u32; 581 556 /* Writing 0 to the status port triggers device reset. */ 582 557 if (u32 == 0) 583 rc = pCallbacks->pfnReset(p State);558 rc = pCallbacks->pfnReset(pDevIns); 584 559 else if (fHasBecomeReady) 585 560 { … … 592 567 PDMPciDevSetCommand(pPciDev, PDMPciDevGetCommand(pPciDev) | PCI_COMMAND_BUSMASTER); 593 568 594 pCallbacks->pfnReady(p State);569 pCallbacks->pfnReady(pDevIns); 595 570 } 596 571 break; 597 572 598 573 default: 599 if ( Port >= VPCI_CONFIG)600 rc = pCallbacks->pfnSetConfig(p State,Port - VPCI_CONFIG, cb, &u32);574 if (offPort >= VPCI_CONFIG) 575 rc = pCallbacks->pfnSetConfig(pThis, offPort - VPCI_CONFIG, cb, &u32); 601 576 else 602 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "%s vpciIOPortOut: no valid port at offset Port=%RTiop cb=%08x\n",603 INSTANCE(p State),Port, cb);577 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "%s vpciIOPortOut: no valid port at offset offPort=%RTiop cb=%08x\n", 578 INSTANCE(pThis), offPort, cb); 604 579 break; 605 580 } 606 581 607 STAM_PROFILE_ADV_STOP(&p State->CTX_SUFF(StatIOWrite), a);582 STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF(StatIOWrite), a); 608 583 return rc; 609 584 } … … 612 587 613 588 /** 614 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 615 */ 616 void *vpciQueryInterface(struct PDMIBASE *pInterface, const char *pszIID) 617 { 618 VPCISTATE *pThis = IFACE_TO_STATE(pInterface, IBase); 619 Assert(&pThis->IBase == pInterface); 620 621 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase); 622 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds); 589 * Handles common IBase.pfnQueryInterface requests. 590 */ 591 void *vpciR3QueryInterface(PVPCISTATECC pThisCC, const char *pszIID) 592 { 593 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThisCC->IBase); 594 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThisCC->ILeds); 623 595 return NULL; 624 596 } 625 597 626 598 /** 627 * Gets the pointer to the status LED of a unit. 599 * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed} 600 */ 601 static DECLCALLBACK(int) vpciR3QueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed) 602 { 603 PVPCISTATECC pThisCC = RT_FROM_MEMBER(pInterface, VPCISTATECC, ILeds); 604 if (iLUN == 0) 605 { 606 *ppLed = &pThisCC->pShared->led; 607 return VINF_SUCCESS; 608 } 609 return VERR_PDM_LUN_NOT_FOUND; 610 } 611 612 /** 613 * Turns on/off the write status LED. 628 614 * 629 615 * @returns VBox status code. 630 * @param pInterface Pointer to the interface structure. 631 * @param iLUN The unit which status LED we desire. 632 * @param ppLed Where to store the LED pointer. 633 * @thread EMT 634 */ 635 static DECLCALLBACK(int) vpciQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed) 636 { 637 VPCISTATE *pState = IFACE_TO_STATE(pInterface, ILeds); 638 int rc = VERR_PDM_LUN_NOT_FOUND; 639 640 if (iLUN == 0) 641 { 642 *ppLed = &pState->led; 643 rc = VINF_SUCCESS; 644 } 645 return rc; 646 } 647 648 /** 649 * Turns on/off the write status LED. 616 * @param pThis Pointer to the device state structure. 617 * @param fOn New LED state. 618 */ 619 void vpciR3SetWriteLed(PVPCISTATE pThis, bool fOn) 620 { 621 LogFlow(("%s vpciR3SetWriteLed: %s\n", INSTANCE(pThis), fOn?"on":"off")); 622 if (fOn) 623 pThis->led.Asserted.s.fWriting = pThis->led.Actual.s.fWriting = 1; 624 else 625 pThis->led.Actual.s.fWriting = fOn; 626 } 627 628 /** 629 * Turns on/off the read status LED. 650 630 * 651 631 * @returns VBox status code. 652 * @param p StatePointer to the device state structure.632 * @param pThis Pointer to the device state structure. 653 633 * @param fOn New LED state. 654 634 */ 655 void vpci SetWriteLed(PVPCISTATE pState, bool fOn)656 { 657 LogFlow(("%s vpci SetWriteLed: %s\n", INSTANCE(pState), fOn?"on":"off"));635 void vpciR3SetReadLed(PVPCISTATE pThis, bool fOn) 636 { 637 LogFlow(("%s vpciR3SetReadLed: %s\n", INSTANCE(pThis), fOn?"on":"off")); 658 638 if (fOn) 659 p State->led.Asserted.s.fWriting = pState->led.Actual.s.fWriting = 1;639 pThis->led.Asserted.s.fReading = pThis->led.Actual.s.fReading = 1; 660 640 else 661 pState->led.Actual.s.fWriting = fOn; 662 } 663 664 /** 665 * Turns on/off the read status LED. 666 * 667 * @returns VBox status code. 668 * @param pState Pointer to the device state structure. 669 * @param fOn New LED state. 670 */ 671 void vpciSetReadLed(PVPCISTATE pState, bool fOn) 672 { 673 LogFlow(("%s vpciSetReadLed: %s\n", INSTANCE(pState), fOn?"on":"off")); 674 if (fOn) 675 pState->led.Asserted.s.fReading = pState->led.Actual.s.fReading = 1; 676 else 677 pState->led.Actual.s.fReading = fOn; 678 } 679 680 681 #if 0 /* unused */ 641 pThis->led.Actual.s.fReading = fOn; 642 } 643 644 645 # if 0 /* unused */ 682 646 /** 683 647 * Sets 32-bit register in PCI configuration space. … … 692 656 *(uint32_t*)&refPciDev.config[uOffset] = u32Value; 693 657 } 694 #endif /* unused */ 695 696 697 #ifdef DEBUG 698 static void vpciDumpState(PVPCISTATE pState, const char *pcszCaller) 699 { 700 Log2(("vpciDumpState: (called from %s)\n" 701 " uGuestFeatures = 0x%08x\n" 702 " uQueueSelector = 0x%04x\n" 703 " uStatus = 0x%02x\n" 704 " uISR = 0x%02x\n", 705 pcszCaller, 706 pState->uGuestFeatures, 707 pState->uQueueSelector, 708 pState->uStatus, 709 pState->uISR)); 710 711 for (unsigned i = 0; i < pState->nQueues; i++) 712 Log2((" %s queue:\n" 713 " VRing.uSize = %u\n" 714 " VRing.addrDescriptors = %p\n" 715 " VRing.addrAvail = %p\n" 716 " VRing.addrUsed = %p\n" 717 " uNextAvailIndex = %u\n" 718 " uNextUsedIndex = %u\n" 719 " uPageNumber = %x\n", 720 pState->Queues[i].pcszName, 721 pState->Queues[i].VRing.uSize, 722 pState->Queues[i].VRing.addrDescriptors, 723 pState->Queues[i].VRing.addrAvail, 724 pState->Queues[i].VRing.addrUsed, 725 pState->Queues[i].uNextAvailIndex, 726 pState->Queues[i].uNextUsedIndex, 727 pState->Queues[i].uPageNumber)); 728 } 729 #else 730 # define vpciDumpState(x, s) do {} while (0) 731 #endif 732 733 /** 734 * Saves the state of device. 658 # endif /* unused */ 659 660 661 /** 662 * Dumps the state (useful for both logging and info items). 663 */ 664 void vpcR3iDumpStateWorker(PVPCISTATE pThis, PCDBGFINFOHLP pHlp) 665 { 666 667 pHlp->pfnPrintf(pHlp, 668 " uGuestFeatures = 0x%08x\n" 669 " uQueueSelector = 0x%04x\n" 670 " uStatus = 0x%02x\n" 671 " uISR = 0x%02x\n", 672 pThis->uGuestFeatures, 673 pThis->uQueueSelector, 674 pThis->uStatus, 675 pThis->uISR); 676 677 for (unsigned i = 0; i < pThis->cQueues; i++) 678 pHlp->pfnPrintf(pHlp, 679 " %s queue:\n" 680 " VRing.uSize = %u\n" 681 " VRing.addrDescriptors = %p\n" 682 " VRing.addrAvail = %p\n" 683 " VRing.addrUsed = %p\n" 684 " uNextAvailIndex = %u\n" 685 " uNextUsedIndex = %u\n" 686 " uPageNumber = %x\n", 687 pThis->Queues[i].szName, 688 pThis->Queues[i].VRing.uSize, 689 pThis->Queues[i].VRing.addrDescriptors, 690 pThis->Queues[i].VRing.addrAvail, 691 pThis->Queues[i].VRing.addrUsed, 692 pThis->Queues[i].uNextAvailIndex, 693 pThis->Queues[i].uNextUsedIndex, 694 pThis->Queues[i].uPageNumber); 695 } 696 697 # ifdef LOG_ENABLED 698 void vpciR3DumpState(PVPCISTATE pThis, const char *pcszCaller) 699 { 700 if (LogIs2Enabled()) 701 { 702 Log2(("vpciR3DumpState: (called from %s)\n", pcszCaller)); 703 vpcR3iDumpStateWorker(pThis, DBGFR3InfoLogHlp()); 704 } 705 } 706 # else 707 # define vpciR3DumpState(x, s) do {} while (0) 708 # endif 709 710 /** 711 * Saved the core virtio state. 735 712 * 736 713 * @returns VBox status code. 737 * @param pDevIns The device instance. 714 * @param pHlp The device helpers. 715 * @param pThis The shared virtio core instance data. 738 716 * @param pSSM The handle to the saved state. 739 717 */ 740 int vpciSaveExec(PVPCISTATE pState, PSSMHANDLE pSSM) 741 { 742 int rc; 743 744 vpciDumpState(pState, "vpciSaveExec"); 745 746 rc = SSMR3PutU32(pSSM, pState->uGuestFeatures); 718 int vpciR3SaveExec(PCPDMDEVHLPR3 pHlp, PVPCISTATE pThis, PSSMHANDLE pSSM) 719 { 720 vpciR3DumpState(pThis, "vpciR3SaveExec"); 721 722 pHlp->pfnSSMPutU32(pSSM, pThis->uGuestFeatures); 723 pHlp->pfnSSMPutU16(pSSM, pThis->uQueueSelector); 724 pHlp->pfnSSMPutU8( pSSM, pThis->uStatus); 725 pHlp->pfnSSMPutU8( pSSM, pThis->uISR); 726 727 /* Save queue states */ 728 int rc = pHlp->pfnSSMPutU32(pSSM, pThis->cQueues); 747 729 AssertRCReturn(rc, rc); 748 rc = SSMR3PutU16(pSSM, pState->uQueueSelector); 749 AssertRCReturn(rc, rc); 750 rc = SSMR3PutU8( pSSM, pState->uStatus); 751 AssertRCReturn(rc, rc); 752 rc = SSMR3PutU8( pSSM, pState->uISR); 753 AssertRCReturn(rc, rc); 754 755 /* Save queue states */ 756 rc = SSMR3PutU32(pSSM, pState->nQueues); 757 AssertRCReturn(rc, rc); 758 for (unsigned i = 0; i < pState->nQueues; i++) 759 { 760 rc = SSMR3PutU16(pSSM, pState->Queues[i].VRing.uSize); 761 AssertRCReturn(rc, rc); 762 rc = SSMR3PutU32(pSSM, pState->Queues[i].uPageNumber); 763 AssertRCReturn(rc, rc); 764 rc = SSMR3PutU16(pSSM, pState->Queues[i].uNextAvailIndex); 765 AssertRCReturn(rc, rc); 766 rc = SSMR3PutU16(pSSM, pState->Queues[i].uNextUsedIndex); 730 for (unsigned i = 0; i < pThis->cQueues; i++) 731 { 732 pHlp->pfnSSMPutU16(pSSM, pThis->Queues[i].VRing.uSize); 733 pHlp->pfnSSMPutU32(pSSM, pThis->Queues[i].uPageNumber); 734 pHlp->pfnSSMPutU16(pSSM, pThis->Queues[i].uNextAvailIndex); 735 rc = pHlp->pfnSSMPutU16(pSSM, pThis->Queues[i].uNextUsedIndex); 767 736 AssertRCReturn(rc, rc); 768 737 } … … 775 744 * 776 745 * @returns VBox status code. 777 * @param pDevIns The device instance. 746 * @param pHlp The device helpers. 747 * @param pThis The shared virtio core instance data. 778 748 * @param pSSM The handle to the saved state. 779 749 * @param uVersion The data unit version number. 780 750 * @param uPass The data pass. 781 */ 782 int vpciLoadExec(PVPCISTATE pState, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t nQueues) 751 * @param cQueues The default queue count (for old states). 752 */ 753 int vpciR3LoadExec(PCPDMDEVHLPR3 pHlp, PVPCISTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t cQueues) 783 754 { 784 755 int rc; … … 787 758 { 788 759 /* Restore state data */ 789 rc = SSMR3GetU32(pSSM, &pState->uGuestFeatures); 790 AssertRCReturn(rc, rc); 791 rc = SSMR3GetU16(pSSM, &pState->uQueueSelector); 792 AssertRCReturn(rc, rc); 793 rc = SSMR3GetU8( pSSM, &pState->uStatus); 794 AssertRCReturn(rc, rc); 795 rc = SSMR3GetU8( pSSM, &pState->uISR); 796 AssertRCReturn(rc, rc); 760 pHlp->pfnSSMGetU32(pSSM, &pThis->uGuestFeatures); 761 pHlp->pfnSSMGetU16(pSSM, &pThis->uQueueSelector); 762 pHlp->pfnSSMGetU8( pSSM, &pThis->uStatus); 763 pHlp->pfnSSMGetU8( pSSM, &pThis->uISR); 797 764 798 765 /* Restore queues */ 799 766 if (uVersion > VIRTIO_SAVEDSTATE_VERSION_3_1_BETA1) 800 767 { 801 rc = SSMR3GetU32(pSSM, &pState->nQueues);768 rc = pHlp->pfnSSMGetU32(pSSM, &pThis->cQueues); 802 769 AssertRCReturn(rc, rc); 803 770 } 804 771 else 805 p State->nQueues = nQueues;806 AssertLogRelMsgReturn(p State->nQueues <= VIRTIO_MAX_NQUEUES, ("%#x\n", pState->nQueues), VERR_SSM_LOAD_CONFIG_MISMATCH);807 AssertLogRelMsgReturn(p State->uQueueSelector < pState->nQueues || (pState->nQueues == 0 && pState->uQueueSelector),808 ("uQueueSelector=%u nQueues=%u\n", pState->uQueueSelector, pState->nQueues),772 pThis->cQueues = cQueues; 773 AssertLogRelMsgReturn(pThis->cQueues <= VIRTIO_MAX_NQUEUES, ("%#x\n", pThis->cQueues), VERR_SSM_LOAD_CONFIG_MISMATCH); 774 AssertLogRelMsgReturn(pThis->uQueueSelector < pThis->cQueues || (pThis->cQueues == 0 && pThis->uQueueSelector), 775 ("uQueueSelector=%u cQueues=%u\n", pThis->uQueueSelector, pThis->cQueues), 809 776 VERR_SSM_LOAD_CONFIG_MISMATCH); 810 777 811 for (unsigned i = 0; i < p State->nQueues; i++)778 for (unsigned i = 0; i < pThis->cQueues; i++) 812 779 { 813 rc = SSMR3GetU16(pSSM, &pState->Queues[i].VRing.uSize);780 rc = pHlp->pfnSSMGetU16(pSSM, &pThis->Queues[i].VRing.uSize); 814 781 AssertRCReturn(rc, rc); 815 rc = SSMR3GetU32(pSSM, &pState->Queues[i].uPageNumber);782 rc = pHlp->pfnSSMGetU32(pSSM, &pThis->Queues[i].uPageNumber); 816 783 AssertRCReturn(rc, rc); 817 784 818 if (p State->Queues[i].uPageNumber)819 vqueueInit(&p State->Queues[i], pState->Queues[i].uPageNumber);820 821 rc = SSMR3GetU16(pSSM, &pState->Queues[i].uNextAvailIndex);785 if (pThis->Queues[i].uPageNumber) 786 vqueueInit(&pThis->Queues[i], pThis->Queues[i].uPageNumber); 787 788 rc = pHlp->pfnSSMGetU16(pSSM, &pThis->Queues[i].uNextAvailIndex); 822 789 AssertRCReturn(rc, rc); 823 rc = SSMR3GetU16(pSSM, &pState->Queues[i].uNextUsedIndex);790 rc = pHlp->pfnSSMGetU16(pSSM, &pThis->Queues[i].uNextUsedIndex); 824 791 AssertRCReturn(rc, rc); 825 792 } 826 793 } 827 794 828 vpci DumpState(pState, "vpciLoadExec");795 vpciR3DumpState(pThis, "vpciLoadExec"); 829 796 830 797 return VINF_SUCCESS; … … 839 806 * @thread EMT 840 807 */ 841 static DECLCALLBACK(void) vpciConfigure(PPDMPCIDEV pPciDev, 842 uint16_t uDeviceId, 843 uint16_t uClass) 808 static void vpciConfigure(PPDMPCIDEV pPciDev, uint16_t uDeviceId, uint16_t uClass) 844 809 { 845 810 /* Configure PCI Device, assume 32-bit mode ******************************/ … … 857 822 PDMPciDevSetByte(pPciDev, VBOX_PCI_INTERRUPT_PIN, 0x01); 858 823 859 # ifdef VBOX_WITH_MSI_DEVICES824 # ifdef VBOX_WITH_MSI_DEVICES 860 825 PDMPciDevSetCapabilityList(pPciDev, 0x80); 861 826 PDMPciDevSetStatus(pPciDev, VBOX_PCI_STATUS_CAP_LIST); 862 #endif 863 } 864 865 #ifdef VBOX_WITH_STATISTICS 866 /* WARNING! This function must never be used in multithreaded context! */ 867 static const char *vpciCounter(const char *pszDevFmt, 868 const char *pszCounter) 869 { 870 static char s_szCounterName[80]; 871 872 RTStrPrintf(s_szCounterName, sizeof(s_szCounterName), 873 "/Devices/%s/%s", pszDevFmt, pszCounter); 874 875 return s_szCounterName; 876 } 877 #endif 878 879 /// @todo header 880 int vpciConstruct(PPDMDEVINS pDevIns, VPCISTATE *pState, 881 int iInstance, const char *pcszNameFmt, 882 uint16_t uDeviceId, uint16_t uClass, 883 uint32_t nQueues) 884 { 885 /* Init handles and log related stuff. */ 886 RTStrPrintf(pState->szInstance, sizeof(pState->szInstance), 887 pcszNameFmt, iInstance); 888 889 pState->pDevInsR3 = pDevIns; 890 pState->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 891 pState->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 892 pState->led.u32Magic = PDMLED_MAGIC; 893 894 pState->ILeds.pfnQueryStatusLed = vpciQueryStatusLed; 827 # endif 828 } 829 830 831 int vpciR3Init(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVPCISTATECC pThisCC, uint16_t uDeviceId, uint16_t uClass, uint32_t cQueues) 832 { 833 /* Init data members. */ 834 pThis->cQueues = cQueues; 835 pThis->led.u32Magic = PDMLED_MAGIC; 836 pThisCC->pShared = pThis; 837 pThisCC->ILeds.pfnQueryStatusLed = vpciR3QueryStatusLed; 838 AssertReturn(pThisCC->IBase.pfnQueryInterface, VERR_INVALID_POINTER); 839 AssertReturn(pThis->szInstance[0], VERR_INVALID_PARAMETER); 840 AssertReturn(strlen(pThis->szInstance) < sizeof(pThis->szInstance), VERR_INVALID_PARAMETER); 895 841 896 842 /* Initialize critical section. */ 897 int rc = PDMDevHlpCritSectInit(pDevIns, &pState->cs, RT_SRC_POS, "%s", pState->szInstance); 898 if (RT_FAILURE(rc)) 899 return rc; 900 843 int rc = PDMDevHlpCritSectInit(pDevIns, &pThis->cs, RT_SRC_POS, "%s", pThis->szInstance); 844 AssertRCReturn(rc, rc); 845 846 /* 847 * Set up the PCI device. 848 */ 901 849 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; 902 850 PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev); 851 903 852 /* Set PCI config registers */ 904 853 vpciConfigure(pPciDev, uDeviceId, uClass); 854 905 855 /* Register PCI device */ 906 856 rc = PDMDevHlpPCIRegister(pDevIns, pPciDev); 907 if (RT_FAILURE(rc)) 908 return rc; 909 910 #ifdef VBOX_WITH_MSI_DEVICES 911 #if 0 857 AssertRCReturn(rc, rc); 858 859 # ifdef VBOX_WITH_MSI_DEVICES 860 # if 0 912 861 { 913 862 PDMMSIREG aMsiReg; … … 920 869 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &aMsiReg); 921 870 if (RT_FAILURE (rc)) 922 PCIDevSetCapabilityList(&p State->pciDevice, 0x0);871 PCIDevSetCapabilityList(&pThis->pciDevice, 0x0); 923 872 } 924 #endif 925 #endif 926 927 /* Status driver */ 873 # endif 874 # endif 875 876 /* 877 * Attach the status driver (optional). 878 */ 928 879 PPDMIBASE pBase; 929 rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pState->IBase, &pBase, "Status Port"); 930 if (RT_FAILURE(rc)) 880 rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pThisCC->IBase, &pBase, "Status Port"); 881 if (RT_SUCCESS(rc)) 882 pThisCC->pLedsConnector = PDMIBASE_QUERY_INTERFACE(pBase, PDMILEDCONNECTORS); 883 else if (rc != VERR_PDM_NO_ATTACHED_DRIVER) 931 884 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach the status LUN")); 932 pState->pLedsConnector = PDMIBASE_QUERY_INTERFACE(pBase, PDMILEDCONNECTORS); 933 934 pState->nQueues = nQueues;935 936 # if defined(VBOX_WITH_STATISTICS)937 PDMDevHlpSTAMRegister F(pDevIns, &pState->StatIOReadR3, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO reads in R3", vpciCounter(pcszNameFmt, "IO/ReadR3"), iInstance);938 PDMDevHlpSTAMRegister F(pDevIns, &pState->StatIOReadR0, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO reads in R0", vpciCounter(pcszNameFmt, "IO/ReadR0"), iInstance);939 PDMDevHlpSTAMRegister F(pDevIns, &pState->StatIOReadRC, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO reads in RC", vpciCounter(pcszNameFmt, "IO/ReadRC"), iInstance);940 PDMDevHlpSTAMRegister F(pDevIns, &pState->StatIOWriteR3, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO writes in R3", vpciCounter(pcszNameFmt, "IO/WriteR3"), iInstance);941 PDMDevHlpSTAMRegister F(pDevIns, &pState->StatIOWriteR0, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO writes in R0", vpciCounter(pcszNameFmt, "IO/WriteR0"), iInstance);942 PDMDevHlpSTAMRegister F(pDevIns, &pState->StatIOWriteRC, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO writes in RC", vpciCounter(pcszNameFmt, "IO/WriteRC"), iInstance);943 PDMDevHlpSTAMRegister F(pDevIns, &pState->StatIntsRaised, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of raised interrupts", vpciCounter(pcszNameFmt, "Interrupts/Raised"), iInstance);944 PDMDevHlpSTAMRegister F(pDevIns, &pState->StatIntsSkipped, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of skipped interrupts", vpciCounter(pcszNameFmt, "Interrupts/Skipped"), iInstance);945 PDMDevHlpSTAMRegister F(pDevIns, &pState->StatCsR3, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling CS wait in R3", vpciCounter(pcszNameFmt, "Cs/CsR3"), iInstance);946 PDMDevHlpSTAMRegister F(pDevIns, &pState->StatCsR0, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling CS wait in R0", vpciCounter(pcszNameFmt, "Cs/CsR0"), iInstance);947 PDMDevHlpSTAMRegister F(pDevIns, &pState->StatCsRC, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling CS wait in RC", vpciCounter(pcszNameFmt, "Cs/CsRC"), iInstance);948 # endif /* VBOX_WITH_STATISTICS */949 950 return rc;885 886 /* 887 * Statistics. 888 */ 889 # ifdef VBOX_WITH_STATISTICS 890 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIOReadR3, STAMTYPE_PROFILE, "IO/ReadR3", STAMUNIT_TICKS_PER_CALL, "Profiling IO reads in R3"); 891 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIOReadR0, STAMTYPE_PROFILE, "IO/ReadR0", STAMUNIT_TICKS_PER_CALL, "Profiling IO reads in R0"); 892 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIOReadRC, STAMTYPE_PROFILE, "IO/ReadRC", STAMUNIT_TICKS_PER_CALL, "Profiling IO reads in RC"); 893 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIOWriteR3, STAMTYPE_PROFILE, "IO/WriteR3", STAMUNIT_TICKS_PER_CALL, "Profiling IO writes in R3"); 894 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIOWriteR0, STAMTYPE_PROFILE, "IO/WriteR0", STAMUNIT_TICKS_PER_CALL, "Profiling IO writes in R0"); 895 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIOWriteRC, STAMTYPE_PROFILE, "IO/WriteRC", STAMUNIT_TICKS_PER_CALL, "Profiling IO writes in RC"); 896 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIntsRaised, STAMTYPE_COUNTER, "Interrupts/Raised", STAMUNIT_OCCURENCES, "Number of raised interrupts"); 897 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIntsSkipped, STAMTYPE_COUNTER, "Interrupts/Skipped", STAMUNIT_OCCURENCES, "Number of skipped interrupts"); 898 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatCsR3, STAMTYPE_PROFILE, "Cs/CsR3", STAMUNIT_TICKS_PER_CALL, "Profiling CS wait in R3"); 899 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatCsR0, STAMTYPE_PROFILE, "Cs/CsR0", STAMUNIT_TICKS_PER_CALL, "Profiling CS wait in R0"); 900 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatCsRC, STAMTYPE_PROFILE, "Cs/CsRC", STAMUNIT_TICKS_PER_CALL, "Profiling CS wait in RC"); 901 # endif /* VBOX_WITH_STATISTICS */ 902 903 return VINF_SUCCESS; 951 904 } 952 905 … … 957 910 * 958 911 * @returns VBox status code. 959 * @param p State The device state structure.960 */ 961 int vpci Destruct(VPCISTATE* pState)962 { 963 Log(("%s Destroying PCI instance\n", INSTANCE(p State)));964 965 if (PDM CritSectIsInitialized(&pState->cs))966 PDM R3CritSectDelete(&pState->cs);912 * @param pThis The shared virtio core instance data. 913 */ 914 int vpciR3Term(PPDMDEVINS pDevIns, PVPCISTATE pThis) 915 { 916 Log(("%s Destroying PCI instance\n", INSTANCE(pThis))); 917 918 if (PDMDevHlpCritSectIsInitialized(pDevIns, &pThis->cs)) 919 PDMDevHlpCritSectDelete(pDevIns, &pThis->cs); 967 920 968 921 return VINF_SUCCESS; 969 922 } 970 923 971 /** 972 * Device relocation callback. 973 * 974 * When this callback is called the device instance data, and if the 975 * device have a GC component, is being relocated, or/and the selectors 976 * have been changed. The device must use the chance to perform the 977 * necessary pointer relocations and data updates. 978 * 979 * Before the GC code is executed the first time, this function will be 980 * called with a 0 delta so GC pointer calculations can be one in one place. 981 * 982 * @param pDevIns Pointer to the device instance. 983 * @param offDelta The relocation delta relative to the old location. 984 * 985 * @remark A relocation CANNOT fail. 986 */ 987 void vpciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) 988 { 989 RT_NOREF(offDelta); 990 VPCISTATE *pState = PDMINS_2_DATA(pDevIns, VPCISTATE*); 991 pState->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 992 // TBD 993 } 994 995 PVQUEUE vpciAddQueue(VPCISTATE* pState, unsigned uSize, PFNVPCIQUEUECALLBACK pfnCallback, const char *pcszName) 996 { 997 PVQUEUE pQueue = NULL; 924 PVQUEUE vpciR3AddQueue(PVPCISTATE pThis, PVPCISTATECC pThisCC, unsigned uSize, 925 PFNVPCIQUEUECALLBACK pfnCallback, const char *pcszName) 926 { 998 927 /* Find an empty queue slot */ 999 for (unsigned i = 0; i < p State->nQueues; i++)1000 { 1001 if (p State->Queues[i].VRing.uSize == 0)928 for (unsigned i = 0; i < pThis->cQueues; i++) 929 { 930 if (pThis->Queues[i].VRing.uSize == 0) 1002 931 { 1003 pQueue = &pState->Queues[i]; 1004 break; 932 PVQUEUE pQueue = &pThis->Queues[i]; 933 pQueue->VRing.uSize = uSize; 934 pQueue->VRing.addrDescriptors = 0; 935 pQueue->uPageNumber = 0; 936 int rc = RTStrCopy(pQueue->szName, sizeof(pQueue->szName), pcszName); 937 AssertRC(rc); 938 pThisCC->Queues[i].pfnCallback = pfnCallback; 939 return pQueue; 1005 940 } 1006 941 } 1007 1008 if (!pQueue) 1009 { 1010 Log(("%s Too many queues being added, no empty slots available!\n", INSTANCE(pState))); 1011 } 1012 else 1013 { 1014 pQueue->VRing.uSize = uSize; 1015 pQueue->VRing.addrDescriptors = 0; 1016 pQueue->uPageNumber = 0; 1017 pQueue->pfnCallback = pfnCallback; 1018 pQueue->pcszName = pcszName; 1019 } 1020 1021 return pQueue; 1022 } 1023 1024 #endif /* IN_RING3 */ 1025 1026 #endif /* VBOX_DEVICE_STRUCT_TESTCASE */ 1027 942 AssertMsgFailedReturn(("%s Too many queues being added, no empty slots available!\n", INSTANCE(pThis)), NULL); 943 } 944 945 #else /* !IN_RING3 */ 946 947 /** 948 * Does ring-0/raw-mode initialization. 949 */ 950 int vpciRZInit(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVPCISTATECC pThisCC) 951 { 952 RT_NOREF(pDevIns, pThis, pThisCC); 953 return VINF_SUCCESS; 954 } 955 956 #endif /* !IN_RING3 */ 957 -
trunk/src/VBox/Devices/VirtIO/Virtio.h
r81703 r81720 25 25 26 26 27 /** Pointer to the core (/common) state of a VirtIO PCI device.*/27 /** Pointer to the core shared state of a VirtIO PCI device */ 28 28 typedef struct VPCISTATE *PVPCISTATE; 29 /** Pointer to the core ring-3 state of a VirtIO PCI device */ 30 typedef struct VPCISTATER3 *PVPCISTATER3; 31 /** Pointer to the core ring-0 state of a VirtIO PCI device */ 32 typedef struct VPCISTATER0 *PVPCISTATER0; 33 /** Pointer to the core raw-mode state of a VirtIO PCI device */ 34 typedef struct VPCISTATERC *PVPCISTATERC; 35 36 /** Pointer to the core current context state of a VirtIO PCI device */ 37 typedef CTX_SUFF(PVPCISTATE) PVPCISTATECC; 38 /** The core current context state of a VirtIO PCI device */ 39 typedef struct CTX_SUFF(VPCISTATE) VPCISTATECC; 29 40 30 41 … … 121 132 typedef VRING *PVRING; 122 133 134 typedef struct VQUEUE 135 { 136 VRING VRing; 137 uint16_t uNextAvailIndex; 138 uint16_t uNextUsedIndex; 139 uint32_t uPageNumber; 140 char szName[16]; 141 } VQUEUE; 142 typedef VQUEUE *PVQUEUE; 143 123 144 /** 124 145 * Queue callback (consumer?). 125 146 * 126 147 * @param pDevIns The device instance. 127 * @param pVPciState Pointer to the VirtIO PCI core state.128 148 * @param pQueue Pointer to the queue structure. 129 149 */ 130 typedef DECLCALLBACK(void) FNVPCIQUEUECALLBACK(PPDMDEVINS pDevIns, PV PCISTATE pVPciState, struct VQueue *pQueue);150 typedef DECLCALLBACK(void) FNVPCIQUEUECALLBACK(PPDMDEVINS pDevIns, PVQUEUE pQueue); 131 151 /** Pointer to a VQUEUE callback function. */ 132 152 typedef FNVPCIQUEUECALLBACK *PFNVPCIQUEUECALLBACK; 133 153 134 typedef struct VQueue 135 { 136 VRING VRing; 137 uint16_t uNextAvailIndex; 138 uint16_t uNextUsedIndex; 139 uint32_t uPageNumber; 154 typedef struct VQUEUER3 155 { 140 156 R3PTRTYPE(PFNVPCIQUEUECALLBACK) pfnCallback; 141 R3PTRTYPE(const char *) pcszName; 142 } VQUEUE; 143 typedef VQUEUE *PVQUEUE; 157 } VQUEUER3; 158 typedef VQUEUER3 *PVQUEUER3; 144 159 145 160 typedef struct VQueueElemSeg … … 170 185 171 186 /** 172 * The core (/common) state of the VirtIO PCI device 187 * The core shared state of a VirtIO PCI device 188 */ 189 typedef struct VPCISTATE 190 { 191 PDMCRITSECT cs; /**< Critical section - what is it protecting? */ 192 /** Read-only part, never changes after initialization. */ 193 char szInstance[8]; /**< Instance name, e.g. VNet#1. */ 194 195 /* Read/write part, protected with critical section. */ 196 /** Status LED. */ 197 PDMLED led; 198 199 uint32_t uGuestFeatures; 200 uint16_t uQueueSelector; /**< An index in aQueues array. */ 201 uint8_t uStatus; /**< Device Status (bits are device-specific). */ 202 uint8_t uISR; /**< Interrupt Status Register. */ 203 204 /** Number of queues actually used. */ 205 uint32_t cQueues; 206 uint32_t u32Padding; 207 /** Shared queue data. */ 208 VQUEUE Queues[VIRTIO_MAX_NQUEUES]; 209 210 #ifdef VBOX_WITH_STATISTICS 211 STAMPROFILEADV StatIOReadR3; 212 STAMPROFILEADV StatIOReadR0; 213 STAMPROFILEADV StatIOReadRC; 214 STAMPROFILEADV StatIOWriteR3; 215 STAMPROFILEADV StatIOWriteR0; 216 STAMPROFILEADV StatIOWriteRC; 217 STAMCOUNTER StatIntsRaised; 218 STAMCOUNTER StatIntsSkipped; 219 STAMPROFILE StatCsR3; 220 STAMPROFILE StatCsR0; 221 STAMPROFILE StatCsRC; 222 #endif 223 } VPCISTATE; 224 225 226 /** 227 * The core ring-3 state of a VirtIO PCI device 173 228 * 174 229 * @implements PDMILEDPORTS 175 230 */ 176 typedef struct VPCISTATE 177 { 178 PDMCRITSECT cs; /**< Critical section - what is it protecting? */ 179 /* Read-only part, never changes after initialization. */ 180 char szInstance[8]; /**< Instance name, e.g. VNet#1. */ 181 182 #if HC_ARCH_BITS != 64 183 uint32_t padding1; 184 #endif 185 231 typedef struct VPCISTATER3 232 { 186 233 /** Status LUN: Base interface. */ 187 PDMIBASE IBase;234 PDMIBASE IBase; 188 235 /** Status LUN: LED port interface. */ 189 PDMILEDPORTS ILeds;236 PDMILEDPORTS ILeds; 190 237 /** Status LUN: LED connector (peer). */ 191 R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector; 192 193 PPDMDEVINSR3 pDevInsR3; /**< Device instance - R3. */ 194 PPDMDEVINSR0 pDevInsR0; /**< Device instance - R0. */ 195 PPDMDEVINSRC pDevInsRC; /**< Device instance - RC. */ 196 197 #if HC_ARCH_BITS == 64 198 uint32_t padding2; 199 #endif 200 201 /** Base port of I/O space region. */ 202 RTIOPORT IOPortBase; 203 204 /* Read/write part, protected with critical section. */ 205 /** Status LED. */ 206 PDMLED led; 207 208 uint32_t uGuestFeatures; 209 uint16_t uQueueSelector; /**< An index in aQueues array. */ 210 uint8_t uStatus; /**< Device Status (bits are device-specific). */ 211 uint8_t uISR; /**< Interrupt Status Register. */ 212 213 #if HC_ARCH_BITS != 64 214 uint32_t padding3; 215 #endif 216 217 uint32_t nQueues; /**< Actual number of queues used. */ 218 VQUEUE Queues[VIRTIO_MAX_NQUEUES]; 219 220 #ifdef VBOX_WITH_STATISTICS 221 STAMPROFILEADV StatIOReadR3; 222 STAMPROFILEADV StatIOReadR0; 223 STAMPROFILEADV StatIOReadRC; 224 STAMPROFILEADV StatIOWriteR3; 225 STAMPROFILEADV StatIOWriteR0; 226 STAMPROFILEADV StatIOWriteRC; 227 STAMCOUNTER StatIntsRaised; 228 STAMCOUNTER StatIntsSkipped; 229 STAMPROFILE StatCsR3; 230 STAMPROFILE StatCsR0; 231 STAMPROFILE StatCsRC; 232 #endif 233 } VPCISTATE; 238 R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector; 239 /** Pointer to the shared state. */ 240 R3PTRTYPE(PVPCISTATE) pShared; 241 /** Ring-3 per-queue data. */ 242 VQUEUER3 Queues[VIRTIO_MAX_NQUEUES]; 243 } VPCISTATER3; 244 245 246 /** 247 * The core ring-0 state of a VirtIO PCI device 248 */ 249 typedef struct VPCISTATER0 250 { 251 uint64_t uUnused; 252 } VPCISTATER0; 253 254 255 /** 256 * The core raw-mode state of a VirtIO PCI device 257 */ 258 typedef struct VPCISTATERC 259 { 260 uint64_t uUnused; 261 } VPCISTATERC; 262 234 263 235 264 /** @name VirtIO port I/O callbacks. … … 242 271 DECLCALLBACKMEMBER(int, pfnGetConfig)(PVPCISTATE pVPciState, uint32_t offCfg, uint32_t cb, void *pvData); 243 272 DECLCALLBACKMEMBER(int, pfnSetConfig)(PVPCISTATE pVPciState, uint32_t offCfg, uint32_t cb, void *pvData); 244 DECLCALLBACKMEMBER(int, pfnReset)(P VPCISTATE pVPciState);245 DECLCALLBACKMEMBER(void, pfnReady)(P VPCISTATE pVPciState);273 DECLCALLBACKMEMBER(int, pfnReset)(PPDMDEVINS pDevIns); 274 DECLCALLBACKMEMBER(void, pfnReady)(PPDMDEVINS pDevIns); 246 275 } VPCIIOCALLBACKS; 247 276 /** Pointer to a const VirtIO port I/O callback structure. */ … … 249 278 /** @} */ 250 279 251 int vpciRaiseInterrupt(VPCISTATE *pState, int rcBusy, uint8_t u8IntCause); 252 int vpciIOPortIn(PPDMDEVINS pDevIns, 253 PVPCISTATE pState, 254 RTIOPORT port, 255 uint32_t *pu32, 256 unsigned cb, 257 PCVPCIIOCALLBACKS pCallbacks); 258 259 int vpciIOPortOut(PPDMDEVINS pDevIns, 260 PVPCISTATE pState, 261 RTIOPORT port, 262 uint32_t u32, 263 unsigned cb, 264 PCVPCIIOCALLBACKS pCallbacks); 265 266 void vpciSetWriteLed(PVPCISTATE pState, bool fOn); 267 void vpciSetReadLed(PVPCISTATE pState, bool fOn); 268 int vpciSaveExec(PVPCISTATE pState, PSSMHANDLE pSSM); 269 int vpciLoadExec(PVPCISTATE pState, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t nQueues); 270 int vpciConstruct(PPDMDEVINS pDevIns, VPCISTATE *pState, int iInstance, const char *pcszNameFmt, 271 uint16_t uDeviceId, uint16_t uClass, uint32_t nQueues); 272 int vpciDestruct(VPCISTATE* pState); 273 void vpciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta); 274 void vpciReset(PVPCISTATE pState); 275 void *vpciQueryInterface(struct PDMIBASE *pInterface, const char *pszIID); 276 PVQUEUE vpciAddQueue(VPCISTATE* pState, unsigned uSize, PFNVPCIQUEUECALLBACK pfnCallback, const char *pcszName); 280 int vpciR3Init(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVPCISTATECC pThisCC, uint16_t uDeviceId, uint16_t uClass, uint32_t cQueues); 281 int vpciRZInit(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVPCISTATECC pThisCC); 282 int vpciR3Term(PPDMDEVINS pDevIns, PVPCISTATE pThis); 283 284 int vpciRaiseInterrupt(PPDMDEVINS pDevIns, PVPCISTATE pThis, int rcBusy, uint8_t u8IntCause); 285 int vpciIOPortIn(PPDMDEVINS pDevIns, PVPCISTATE pThis, RTIOPORT offPort, 286 uint32_t *pu32, unsigned cb,PCVPCIIOCALLBACKS pCallbacks); 287 int vpciIOPortOut(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVPCISTATECC pThisCC, RTIOPORT offPort, 288 uint32_t u32, unsigned cb, PCVPCIIOCALLBACKS pCallbacks); 289 290 void vpciR3SetWriteLed(PVPCISTATE pThis, bool fOn); 291 void vpciR3SetReadLed(PVPCISTATE pThis, bool fOn); 292 int vpciR3SaveExec(PCPDMDEVHLPR3 pHlp, PVPCISTATE pThis, PSSMHANDLE pSSM); 293 int vpciR3LoadExec(PCPDMDEVHLPR3 pHlp, PVPCISTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t cQueues); 294 void vpciReset(PPDMDEVINS pDevIns, PVPCISTATE pThis); 295 void *vpciR3QueryInterface(PVPCISTATECC pThisCC, const char *pszIID); 296 PVQUEUE vpciR3AddQueue(PVPCISTATE pThis, PVPCISTATECC pThisCC, unsigned uSize, PFNVPCIQUEUECALLBACK pfnCallback, const char *pcszName); 277 297 278 298 #define VPCI_CS 279 DECLINLINE(int) vpciCsEnter( VPCISTATE *pState, int rcBusy)299 DECLINLINE(int) vpciCsEnter(PPDMDEVINS pDevIns, PVPCISTATE pThis, int rcBusy) 280 300 { 281 301 #ifdef VPCI_CS 282 STAM_PROFILE_START(&p State->CTX_SUFF(StatCs), a);283 int rc = PDM CritSectEnter(&pState->cs, rcBusy);284 STAM_PROFILE_STOP(&p State->CTX_SUFF(StatCs), a);302 STAM_PROFILE_START(&pThis->CTX_SUFF(StatCs), a); 303 int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->cs, rcBusy); 304 STAM_PROFILE_STOP(&pThis->CTX_SUFF(StatCs), a); 285 305 return rc; 286 306 #else 307 RT_NOREF(pDevIns, pThis, rcBusy); 287 308 return VINF_SUCCESS; 288 309 #endif 289 310 } 290 311 291 DECLINLINE(void) vpciCsLeave( VPCISTATE *pState)312 DECLINLINE(void) vpciCsLeave(PPDMDEVINS pDevIns, PVPCISTATE pThis) 292 313 { 293 314 #ifdef VPCI_CS 294 PDM CritSectLeave(&pState->cs);315 PDMDevHlpCritSectLeave(pDevIns, &pThis->cs); 295 316 #endif 296 317 } 297 318 298 void vringSetNotification(PVPCISTATE pState, PVRING pVRing, bool fEnabled); 299 300 DECLINLINE(uint16_t) vringReadAvailIndex(PVPCISTATE pState, PVRING pVRing) 301 { 302 uint16_t tmp; 303 304 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 305 pVRing->addrAvail + RT_UOFFSETOF(VRINGAVAIL, uNextFreeIndex), 306 &tmp, sizeof(tmp)); 307 return tmp; 308 } 309 310 bool vqueueSkip(PVPCISTATE pState, PVQUEUE pQueue); 311 bool vqueueGet(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true); 312 void vqueuePut(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t uLen, uint32_t uReserved = 0); 313 void vqueueNotify(PVPCISTATE pState, PVQUEUE pQueue); 314 void vqueueSync(PVPCISTATE pState, PVQUEUE pQueue); 315 316 DECLINLINE(bool) vqueuePeek(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem) 317 { 318 return vqueueGet(pState, pQueue, pElem, /* fRemove */ false); 319 } 320 321 DECLINLINE(bool) vqueueIsReady(PVPCISTATE pState, PVQUEUE pQueue) 322 { 323 NOREF(pState); 319 void vringSetNotification(PPDMDEVINS pDevIns, PVRING pVRing, bool fEnabled); 320 321 DECLINLINE(uint16_t) vringReadAvailIndex(PPDMDEVINS pDevIns, PVRING pVRing) 322 { 323 uint16_t idx = 0; 324 PDMDevHlpPhysRead(pDevIns, pVRing->addrAvail + RT_UOFFSETOF(VRINGAVAIL, uNextFreeIndex), &idx, sizeof(idx)); 325 return idx; 326 } 327 328 bool vqueueSkip(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue); 329 bool vqueueGet(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true); 330 void vqueuePut(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t uLen, uint32_t uReserved = 0); 331 void vqueueNotify(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue); 332 void vqueueSync(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue); 333 334 DECLINLINE(bool) vqueuePeek(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue, PVQUEUEELEM pElem) 335 { 336 return vqueueGet(pDevIns, pThis, pQueue, pElem, /* fRemove */ false); 337 } 338 339 DECLINLINE(bool) vqueueIsReady(PVQUEUE pQueue) 340 { 324 341 return !!pQueue->VRing.addrAvail; 325 342 } 326 343 327 DECLINLINE(bool) vqueueIsEmpty(PVPCISTATE pState, PVQUEUE pQueue) 328 { 329 return (vringReadAvailIndex(pState, &pQueue->VRing) == pQueue->uNextAvailIndex); 330 } 344 DECLINLINE(bool) vqueueIsEmpty(PPDMDEVINS pDevIns, PVQUEUE pQueue) 345 { 346 return vringReadAvailIndex(pDevIns, &pQueue->VRing) == pQueue->uNextAvailIndex; 347 } 348 349 void vpcR3iDumpStateWorker(PVPCISTATE pThis, PCDBGFINFOHLP pHlp); 331 350 332 351 #endif /* !VBOX_INCLUDED_SRC_VirtIO_Virtio_h */
Note:
See TracChangeset
for help on using the changeset viewer.