VirtualBox

Changeset 81720 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 6, 2019 8:23:17 PM (5 years ago)
Author:
vboxsync
Message:

DevVirtioNet,Virtio: Converted to new PDM device model. bugref:9218

Location:
trunk/src/VBox/Devices
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/DevVirtioNet.cpp

    r81709 r81720  
    2121*********************************************************************************************************************************/
    2222#define LOG_GROUP LOG_GROUP_DEV_VIRTIO_NET
    23 #define VNET_GC_SUPPORT
    2423#define VNET_WITH_GSO
    2524#define VNET_WITH_MERGEABLE_RX_BUFS
     
    3231#include <iprt/string.h>
    3332#ifdef IN_RING3
    34 # include <iprt/mem.h>
    3533# include <iprt/uuid.h>
    3634#endif
     
    4644
    4745#define INSTANCE(pThis) pThis->VPCI.szInstance
    48 #define STATUS pThis->config.uStatus
    4946
    5047#ifdef IN_RING3
     
    5249# define VNET_PCI_CLASS              0x0200
    5350# define VNET_N_QUEUES               3
    54 # define VNET_NAME_FMT               "VNet%d"
    5551
    5652# if 0
     
    5854#  define VNET_PCI_CLASS             0x0180
    5955#  define VNET_N_QUEUES              2
    60 #  define VNET_NAME_FMT              "VBlk%d"
    6156# endif
    6257
     
    113108
    114109/**
    115  * Device state structure. Holds the current state of device.
     110 * The virtio-net shared instance data.
    116111 *
    117112 * @extends     VPCISTATE
    118  * @implements  PDMINETWORKDOWN
    119  * @implements  PDMINETWORKCONFIG
    120  */
    121 typedef struct VNetState_st
    122 {
    123     /* VPCISTATE must be the first member! */
     113 */
     114typedef struct VNETSTATE
     115{
    124116    VPCISTATE               VPCI;
    125117
    126118//    PDMCRITSECT             csRx;                           /**< Protects RX queue. */
    127119
    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 
    136120#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;
    148123    uint32_t                u32i;
    149124    uint32_t                u32AvgDiff;
     
    151126    uint32_t                u32MaxDiff;
    152127    uint64_t                u64NanoTS;
    153 #else /* !VNET_TX_DELAY */
    154     /** The support driver session handle. */
    155     R3R0PTRTYPE(PSUPDRVSESSION)     pSupDrvSession;
     128#else  /* !VNET_TX_DELAY */
    156129    /** The event semaphore TX thread waits on. */
    157     SUPSEMEVENT                     hTxEvent;
    158     R3PTRTYPE(PPDMTHREAD)           pTxThread;
     130    SUPSEMEVENT             hTxEvent;
    159131#endif /* !VNET_TX_DELAY */
    160132
     
    184156    bool                    fAllMulti;
    185157    /** The number of actually used slots in aMacTable. */
    186     uint32_t                nMacFilterEntries;
     158    uint32_t                cMacFilterEntries;
    187159    /** Array of MAC addresses accepted by RX filter. */
    188160    RTMAC                   aMacFilter[VNET_MAC_FILTER_LEN];
     
    190162    uint8_t                 aVlanFilter[VNET_MAX_VID / sizeof(uint8_t)];
    191163
    192     R3PTRTYPE(PVQUEUE)      pRxQueue;
    193     R3PTRTYPE(PVQUEUE)      pTxQueue;
    194     R3PTRTYPE(PVQUEUE)      pCtlQueue;
    195164    /* Receive-blocking-related fields ***************************************/
    196165
    197166    /** EMT: Gets signalled when more RX descriptors become available. */
    198167    SUPSEMEVENT             hEventMoreRxDescAvail;
     168
     169    /** Handle of the I/O port range.  */
     170    IOMIOPORTHANDLE         hIoPorts;
    199171
    200172    /** @name Statistic
     
    218190    /** @}  */
    219191} VNETSTATE;
    220 /** Pointer to a virtual I/O network device state. */
     192/** Pointer to the virtio-net shared instance data. */
    221193typedef VNETSTATE *PVNETSTATE;
     194
     195
     196/**
     197 * The virtio-net ring-3 instance data.
     198 *
     199 * @extends     VPCISTATER3
     200 * @implements  PDMINETWORKDOWN
     201 * @implements  PDMINETWORKCONFIG
     202 */
     203typedef 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. */
     227typedef VNETSTATER3 *PVNETSTATER3;
     228
     229
     230/**
     231 * The virtio-net ring-0 instance data.
     232 *
     233 * @extends     VPCISTATER0
     234 */
     235typedef struct VNETSTATER0
     236{
     237    VPCISTATER0             VPCI;
     238} VNETSTATER0;
     239/** Pointer to the virtio-net ring-0 instance data. */
     240typedef VNETSTATER0 *PVNETSTATER0;
     241
     242
     243/**
     244 * The virtio-net raw-mode instance data.
     245 *
     246 * @extends     VPCISTATERC
     247 */
     248typedef struct VNETSTATERC
     249{
     250    VPCISTATERC             VPCI;
     251} VNETSTATERC;
     252/** Pointer to the virtio-net ring-0 instance data. */
     253typedef VNETSTATERC *PVNETSTATERC;
     254
     255
     256/** The virtio-net currenct context instance data. */
     257typedef CTX_SUFF(VNETSTATE) VNETSTATECC;
     258/** Pointer to the virtio-net currenct context instance data. */
     259typedef CTX_SUFF(PVNETSTATE) PVNETSTATECC;
     260
     261
    222262
    223263#ifndef VBOX_DEVICE_STRUCT_TESTCASE
     
    289329}
    290330
    291 DECLINLINE(int) vnetR3CsEnter(PVNETSTATE pThis, int rcBusy)
    292 {
    293     return vpciCsEnter(&pThis->VPCI, rcBusy);
    294 }
    295 
    296 DECLINLINE(void) vnetR3CsLeave(PVNETSTATE pThis)
    297 {
    298     vpciCsLeave(&pThis->VPCI);
     331DECLINLINE(int) vnetR3CsEnter(PPDMDEVINS pDevIns, PVNETSTATE pThis, int rcBusy)
     332{
     333    return vpciCsEnter(pDevIns, &pThis->VPCI, rcBusy);
     334}
     335
     336DECLINLINE(void) vnetR3CsLeave(PPDMDEVINS pDevIns, PVNETSTATE pThis)
     337{
     338    vpciCsLeave(pDevIns, &pThis->VPCI);
    299339}
    300340
     
    322362 * Dump a packet to debug log.
    323363 *
    324  * @param   pThis       The device state structure.
     364 * @param   pThis       The virtio-net shared instance data.
    325365 * @param   pbPacket    The packet.
    326366 * @param   cb          The size of the packet.
     
    346386 * Print features given in uFeatures to debug log.
    347387 *
    348  * @param   pThis      The device state structure.
     388 * @param   pThis      The virtio-net shared instance data.
    349389 * @param   fFeatures   Descriptions of which features to print.
    350390 * @param   pcszText    A string to print before the list of features.
     
    482522 * Hardware reset. Revert all registers to initial values.
    483523 */
    484 static DECLCALLBACK(int) vnetIoCb_Reset(PVPCISTATE pVPciState)
    485 {
    486     PVNETSTATE pThis = RT_FROM_MEMBER(pVPciState, VNETSTATE, VPCI);
     524static 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
    487530    Log(("%s Reset triggered\n", INSTANCE(pThis)));
    488531
     
    493536        return rc;
    494537    }
    495     vpciReset(&pThis->VPCI);
     538    vpciReset(pDevIns, &pThis->VPCI);
    496539    vnetCsRxLeave(pThis);
    497540
    498541    /// @todo Implement reset
    499542    if (pThis->fCableConnected)
    500         STATUS = VNET_S_LINK_UP;
     543        pThis->config.uStatus = VNET_S_LINK_UP;
    501544    else
    502         STATUS = 0;
     545        pThis->config.uStatus = 0;
    503546    Log(("%s vnetIoCb_Reset: Link is %s\n", INSTANCE(pThis), pThis->fCableConnected ? "up" : "down"));
    504547
     
    509552    pThis->fPromiscuous      = true;
    510553    pThis->fAllMulti         = false;
    511     pThis->nMacFilterEntries = 0;
     554    pThis->cMacFilterEntries = 0;
    512555    memset(pThis->aMacFilter,  0, VNET_MAC_FILTER_LEN * sizeof(RTMAC));
    513556    memset(pThis->aVlanFilter, 0, sizeof(pThis->aVlanFilter));
     
    516559    return VINF_IOM_R3_IOPORT_WRITE;
    517560#else
    518     if (pThis->pDrv)
    519         pThis->pDrv->pfnSetPromiscuousMode(pThis->pDrv, true);
     561    if (pThisCC->pDrv)
     562        pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, true);
    520563    return VINF_SUCCESS;
    521564#endif
     
    544587 * Helper function that raises an interrupt if the guest is ready to receive it.
    545588 */
    546 static int vnetR3RaiseInterrupt(PVNETSTATE pThis, int rcBusy, uint8_t u8IntCause)
     589static int vnetR3RaiseInterrupt(PPDMDEVINS pDevIns, PVNETSTATE pThis, int rcBusy, uint8_t u8IntCause)
    547590{
    548591    if (pThis->VPCI.uStatus & VPCI_STATUS_DRV_OK)
    549         return vpciRaiseInterrupt(&pThis->VPCI, rcBusy, u8IntCause);
     592        return vpciRaiseInterrupt(pDevIns, &pThis->VPCI, rcBusy, u8IntCause);
    550593    return rcBusy;
    551594}
     
    561604 * renegotiate any DHCP lease.
    562605 *
    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 */
     610static 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);
    571616        /* Restore the link back in 5 seconds. */
    572         int rc = TMTimerSetMillies(pThis->pLinkUpTimer, pThis->cMsLinkUpDelay);
     617        int rc = PDMDevHlpTimerSetMillies(pDevIns, pThisCC->hLinkUpTimer, pThis->cMsLinkUpDelay);
    573618        AssertRC(rc);
    574619        Log(("%s vnetR3TempLinkDown: Link is down temporarily\n", INSTANCE(pThis)));
     
    582627static DECLCALLBACK(void) vnetR3LinkUpTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    583628{
    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);
    592638    vnetWakeupReceive(pDevIns);
    593     vnetR3CsLeave(pThis);
     639
     640    vnetR3CsLeave(pDevIns, pThis);
     641
    594642    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);
    597645}
    598646
     
    604652 * This function is called when the driver becomes ready.
    605653 */
    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));
     654static 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);
    611658}
    612659
     
    628675
    629676/**
    630  * @callback_method_impl{FNIOMIOPORTIN}
    631  */
    632 PDMBOTHCBDECL(int) vnetIOPortIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb)
     677 * @callback_method_impl{FNIOMIOPORTNEWIN}
     678 */
     679static DECLCALLBACK(VBOXSTRICTRC) vnetIOPortIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
    633680{
    634681    PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);
    635682    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 */
     690static 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);
    646694    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);
    648696}
    649697
     
    660708 *
    661709 * @returns VERR_NET_NO_BUFFER_SPACE if it cannot.
    662  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    663710 * @thread  RX
    664711 */
    665 static int vnetR3CanReceive(PVNETSTATE pThis)
     712static int vnetR3CanReceive(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC)
    666713{
    667714    int rc = vnetCsRxEnter(pThis, VERR_SEM_BUSY);
     
    671718    if (!(pThis->VPCI.uStatus & VPCI_STATUS_DRV_OK))
    672719        rc = VERR_NET_NO_BUFFER_SPACE;
    673     else if (!vqueueIsReady(&pThis->VPCI, pThis->pRxQueue))
     720    else if (!vqueueIsReady(pThisCC->pRxQueue))
    674721        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);
    678725        rc = VERR_NET_NO_BUFFER_SPACE;
    679726    }
    680727    else
    681728    {
    682         vringSetNotification(&pThis->VPCI, &pThis->pRxQueue->VRing, false);
     729        vringSetNotification(pDevIns, &pThisCC->pRxQueue->VRing, false);
    683730        rc = VINF_SUCCESS;
    684731    }
     
    694741static DECLCALLBACK(int) vnetR3NetworkDown_WaitReceiveAvail(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies)
    695742{
    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);
    698746    LogFlow(("%s vnetR3NetworkDown_WaitReceiveAvail(cMillies=%u)\n", INSTANCE(pThis), cMillies));
    699747
    700     int rc = vnetR3CanReceive(pThis);
     748    int rc = vnetR3CanReceive(pDevIns, pThis, pThisCC);
    701749    if (RT_SUCCESS(rc))
    702750        return VINF_SUCCESS;
     
    710758
    711759    VMSTATE enmVMState;
    712     while (RT_LIKELY(   (enmVMState = PDMDevHlpVMState(pThis->VPCI.CTX_SUFF(pDevIns))) == VMSTATE_RUNNING
     760    while (RT_LIKELY(   (enmVMState = PDMDevHlpVMState(pDevIns)) == VMSTATE_RUNNING
    713761                     ||  enmVMState == VMSTATE_RUNNING_LS))
    714762    {
    715         int rc2 = vnetR3CanReceive(pThis);
     763        int rc2 = vnetR3CanReceive(pDevIns, pThis, pThisCC);
    716764        if (RT_SUCCESS(rc2))
    717765        {
     
    733781
    734782/**
    735  * @interface_method_impl{PDMIBASE,pfnQueryInterface}
     783 * @interface_method_impl{PDMIBASE,pfnQueryInterface,
     784 * For VNETSTATECC::VPCI.IBase}
    736785 */
    737786static DECLCALLBACK(void *) vnetQueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
    738787{
    739     PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, VPCI.IBase);
    740     Assert(&pThis->VPCI.IBase == pInterface);
    741 
    742     PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKDOWN, &pThis->INetworkDown);
    743     PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThis->INetworkConfig);
    744     return vpciQueryInterface(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);
    745794}
    746795
     
    802851    Log4(("%s vnetR3AddressFilter: %RTmac (conf) != %RTmac (dest)\n", INSTANCE(pThis), pThis->config.mac.au8, pvBuf));
    803852
    804     for (unsigned i = 0; i < pThis->nMacFilterEntries; i++)
     853    for (unsigned i = 0; i < pThis->cMacFilterEntries; i++)
    805854        if (!memcmp(&pThis->aMacFilter[i], pvBuf, sizeof(RTMAC)))
    806855            return true;
     
    819868 *
    820869 * @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.
    822872 * @param   pvBuf           The available data.
    823873 * @param   cb              Number of bytes available in the buffer.
    824874 * @thread  RX
    825875 */
    826 static int vnetR3HandleRxPacket(PVNETSTATE pThis, const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso)
     876static int vnetR3HandleRxPacket(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC,
     877                                const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso)
    827878{
    828879    VNETHDRMRX  Hdr;
     
    877928        unsigned int nSeg = 0, uElemSize = 0, cbReserved = 0;
    878929
    879         if (!vqueueGet(&pThis->VPCI, pThis->pRxQueue, &elem))
     930        if (!vqueueGet(pDevIns, &pThis->VPCI, pThisCC->pRxQueue, &elem))
    880931        {
    881932            /*
     
    921972        }
    922973        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);
    924975        STAM_PROFILE_STOP(&pThis->StatReceiveStore, a);
    925976        if (!vnetR3MergeableRxBuffers(pThis))
     
    930981    {
    931982        Hdr.u16NumBufs = nElem;
    932         int rc = PDMDevHlpPCIPhysWrite(pThis->VPCI.CTX_SUFF(pDevIns), addrHdrMrx,
     983        int rc = PDMDevHlpPCIPhysWrite(pDevIns, addrHdrMrx,
    933984                                       &Hdr, sizeof(Hdr));
    934985        if (RT_FAILURE(rc))
     
    938989        }
    939990    }
    940     vqueueSync(&pThis->VPCI, pThis->pRxQueue);
     991    vqueueSync(pDevIns, &pThis->VPCI, pThisCC->pRxQueue);
    941992    if (uOffset < cb)
    942993    {
     
    9511002 * @interface_method_impl{PDMINETWORKDOWN,pfnReceiveGso}
    9521003 */
    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);
     1004static 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);
    9581010
    9591011    if (pGso)
     
    9851037
    9861038    Log2(("%s vnetR3NetworkDown_ReceiveGso: pvBuf=%p cb=%u pGso=%p\n", INSTANCE(pThis), pvBuf, cb, pGso));
    987     int rc = vnetR3CanReceive(pThis);
     1039    int rc = vnetR3CanReceive(pDevIns, pThis, pThisCC);
    9881040    if (RT_FAILURE(rc))
    9891041        return rc;
    9901042
    9911043    /* Drop packets if VM is not running or cable is disconnected. */
    992     VMSTATE enmVMState = PDMDevHlpVMState(pThis->VPCI.CTX_SUFF(pDevIns));
     1044    VMSTATE enmVMState = PDMDevHlpVMState(pDevIns);
    9931045    if ((   enmVMState != VMSTATE_RUNNING
    9941046         && enmVMState != VMSTATE_RUNNING_LS)
    995         || !(STATUS & VNET_S_LINK_UP))
     1047        || !(pThis->config.uStatus & VNET_S_LINK_UP))
    9961048        return VINF_SUCCESS;
    9971049
    9981050    STAM_PROFILE_START(&pThis->StatReceive, a);
    999     vpciSetReadLed(&pThis->VPCI, true);
     1051    vpciR3SetReadLed(&pThis->VPCI, true);
    10001052    if (vnetR3AddressFilter(pThis, pvBuf, cb))
    10011053    {
     
    10031055        if (RT_SUCCESS(rc))
    10041056        {
    1005             rc = vnetR3HandleRxPacket(pThis, pvBuf, cb, pGso);
     1057            rc = vnetR3HandleRxPacket(pDevIns, pThis, pThisCC, pvBuf, cb, pGso);
    10061058            STAM_REL_COUNTER_ADD(&pThis->StatReceiveBytes, cb);
    10071059            vnetCsRxLeave(pThis);
    10081060        }
    10091061    }
    1010     vpciSetReadLed(&pThis->VPCI, false);
     1062    vpciR3SetReadLed(&pThis->VPCI, false);
    10111063    STAM_PROFILE_STOP(&pThis->StatReceive, a);
    10121064    return rc;
     
    10221074
    10231075/**
    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}
    10301077 */
    10311078static DECLCALLBACK(int) vnetR3NetworkConfig_GetMac(PPDMINETWORKCONFIG pInterface, PRTMAC pMac)
    10321079{
    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);
    10341082    memcpy(pMac, pThis->config.mac.au8, sizeof(RTMAC));
    10351083    return VINF_SUCCESS;
     
    10371085
    10381086/**
    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}
    10441088 */
    10451089static DECLCALLBACK(PDMNETWORKLINKSTATE) vnetR3NetworkConfig_GetLinkState(PPDMINETWORKCONFIG pInterface)
    10461090{
    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)
    10491094        return PDMNETWORKLINKSTATE_UP;
    10501095    return PDMNETWORKLINKSTATE_DOWN;
    10511096}
    10521097
    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}
    10601100 */
    10611101static DECLCALLBACK(int) vnetR3NetworkConfig_SetLinkState(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState)
    10621102{
    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);
    10651107    bool fNewUp = enmState == PDMNETWORKLINKSTATE_UP;
    10661108
     
    10741116             * notification will be sent when the link actually goes up in vnetR3LinkUpTimer().
    10751117             */
    1076             vnetR3TempLinkDown(pThis);
    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);
    10791121        }
    10801122    }
     
    10851127            Log(("%s Link is up\n", INSTANCE(pThis)));
    10861128            pThis->fCableConnected = true;
    1087             STATUS |= VNET_S_LINK_UP;
    1088             vnetR3RaiseInterrupt(pThis, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
     1129            pThis->config.uStatus |= VNET_S_LINK_UP;
     1130            vnetR3RaiseInterrupt(pDevIns, pThis, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
    10891131        }
    10901132        else
    10911133        {
    10921134            /* The link was brought down explicitly, make sure it won't come up by timer.  */
    1093             TMTimerStop(pThis->pLinkUpTimer);
     1135            PDMDevHlpTimerStop(pDevIns, pThisCC->hLinkUpTimer);
    10941136            Log(("%s Link is down\n", INSTANCE(pThis)));
    10951137            pThis->fCableConnected = false;
    1096             STATUS &= ~VNET_S_LINK_UP;
    1097             vnetR3RaiseInterrupt(pThis, 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);
    11011143    }
    11021144    return VINF_SUCCESS;
    11031145}
    11041146
    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 */
     1150static DECLCALLBACK(void) vnetR3QueueReceive(PPDMDEVINS pDevIns, PVQUEUE pQueue)
     1151{
     1152    PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);
    11081153    RT_NOREF(pThis, pQueue);
    11091154    Log(("%s Receive buffers has been added, waking up receive thread.\n", INSTANCE(pThis)));
     
    11771222    AssertReturnVoid(uStart < cbSize);
    11781223    AssertReturnVoid(uStart + uOffset + sizeof(uint16_t) <= cbSize);
    1179     *(uint16_t*)(pBuf + uStart + uOffset) = vnetR3CSum16(pBuf + uStart, cbSize - uStart);
    1180 }
    1181 
    1182 static bool vnetR3ReadHeader(PVNETSTATE pThis, RTGCPHYS GCPhys, PVNETHDR pHdr, uint32_t cbMax)
    1183 {
    1184     int rc = PDMDevHlpPhysRead(pThis->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
     1227static 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? */
    11851230    if (RT_FAILURE(rc))
    11861231        return false;
     
    12231268}
    12241269
    1225 static int vnetR3TransmitFrame(PVNETSTATE pThis, PPDMSCATTERGATHER pSgBuf, PPDMNETWORKGSO pGso, PVNETHDR pHdr)
     1270static int vnetR3TransmitFrame(PVNETSTATE pThis, PVNETSTATECC pThisCC, PPDMSCATTERGATHER pSgBuf,
     1271                               PPDMNETWORKGSO pGso, PVNETHDR pHdr)
    12261272{
    12271273    vnetR3PacketDump(pThis, (uint8_t *)pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, "--> Outgoing");
     
    12701316    }
    12711317
    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
     1321static void vnetR3TransmitPendingPackets(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC,
     1322                                         PVQUEUE pQueue, bool fOnWorkerThread)
    12761323{
    12771324    /*
     
    12951342    }
    12961343
    1297     PPDMINETWORKUP pDrv = pThis->pDrv;
     1344    PPDMINETWORKUP pDrv = pThisCC->pDrv;
    12981345    if (pDrv)
    12991346    {
     
    13141361
    13151362    Log3(("%s vnetR3TransmitPendingPackets: About to transmit %d pending packets\n",
    1316           INSTANCE(pThis), vringReadAvailIndex(&pThis->VPCI, &pThis->pTxQueue->VRing) - pThis->pTxQueue->uNextAvailIndex));
    1317 
    1318     vpciSetWriteLed(&pThis->VPCI, true);
     1363          INSTANCE(pThis), vringReadAvailIndex(pDevIns, &pThisCC->pTxQueue->VRing) - pThisCC->pTxQueue->uNextAvailIndex));
     1364
     1365    vpciR3SetWriteLed(&pThis->VPCI, true);
    13191366
    13201367    /*
     
    13231370     */
    13241371    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))
    13261373    {
    13271374        unsigned int uOffset = 0;
     
    13471394        if (uSize > VNET_MAX_FRAME_SIZE)
    13481395            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))
    13501397        {
    13511398            RT_UNTRUSTED_VALIDATED_FENCE();
     
    13581405            /** @todo Optimize away the extra copying! (lazy bird) */
    13591406            PPDMSCATTERGATHER pSgBuf;
    1360             int rc = pThis->pDrv->pfnAllocBuf(pThis->pDrv, uSize, pGso, &pSgBuf);
     1407            int rc = pThisCC->pDrv->pfnAllocBuf(pThisCC->pDrv, uSize, pGso, &pSgBuf);
    13611408            if (RT_SUCCESS(rc))
    13621409            {
     
    13681415                {
    13691416                    unsigned int cbSegment = RT_MIN(uSize, elem.aSegsOut[i].cb);
    1370                     PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), elem.aSegsOut[i].addr,
     1417                    PDMDevHlpPhysRead(pDevIns, elem.aSegsOut[i].addr,
    13711418                                      ((uint8_t*)pSgBuf->aSegs[0].pvSeg) + uOffset,
    13721419                                      cbSegment);
     
    13741421                    uSize -= cbSegment;
    13751422                }
    1376                 rc = vnetR3TransmitFrame(pThis, pSgBuf, pGso, &Hdr);
     1423                rc = vnetR3TransmitFrame(pThis, pThisCC, pSgBuf, pGso, &Hdr);
    13771424            }
    13781425            else
     
    13901437
    13911438        /* 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);
    13951442        STAM_PROFILE_ADV_STOP(&pThis->StatTransmit, a);
    13961443    }
    1397     vpciSetWriteLed(&pThis->VPCI, false);
     1444    vpciR3SetWriteLed(&pThis->VPCI, false);
    13981445
    13991446    if (pDrv)
     
    14071454static DECLCALLBACK(void) vnetR3NetworkDown_XmitPending(PPDMINETWORKDOWN pInterface)
    14081455{
    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);
    14101459    STAM_COUNTER_INC(&pThis->StatTransmitByNetwork);
    1411     vnetR3TransmitPendingPackets(pThis, pThis->pTxQueue, false /*fOnWorkerThread*/);
     1460    vnetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pThisCC->pTxQueue, false /*fOnWorkerThread*/);
    14121461}
    14131462
    14141463# ifdef VNET_TX_DELAY
    14151464
    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 */
     1468static 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);
    14241476        Log3(("%s vnetR3QueueTransmit: Got kicked with notification disabled, re-enable notification and flush TX queue\n", INSTANCE(pThis)));
    1425         vnetR3TransmitPendingPackets(pThis, pQueue, false /*fOnWorkerThread*/);
    1426         if (RT_FAILURE(vnetR3CsEnter(pThis, VERR_SEM_BUSY)))
     1477        vnetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pQueue, false /*fOnWorkerThread*/);
     1478        if (RT_FAILURE(vnetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY)))
    14271479            LogRel(("vnetR3QueueTransmit: Failed to enter critical section!/n"));
    14281480        else
    14291481        {
    1430             vringSetNotification(&pThis->VPCI, &pThis->pTxQueue->VRing, true);
    1431             vnetR3CsLeave(pThis);
     1482            vringSetNotification(pDevIns, &pThisCC->pTxQueue->VRing, true);
     1483            vnetR3CsLeave(pDevIns, pThis);
    14321484        }
    14331485    }
    14341486    else
    14351487    {
    1436         if (RT_FAILURE(vnetR3CsEnter(pThis, VERR_SEM_BUSY)))
     1488        if (RT_FAILURE(vnetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY)))
    14371489            LogRel(("vnetR3QueueTransmit: Failed to enter critical section!/n"));
    14381490        else
    14391491        {
    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);
    14421494            pThis->u64NanoTS = RTTimeNanoTS();
    1443             vnetR3CsLeave(pThis);
     1495            vnetR3CsLeave(pDevIns, pThis);
    14441496        }
    14451497    }
     
    14511503static DECLCALLBACK(void) vnetR3TxTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    14521504{
    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);
    14571510    if (u32MicroDiff < pThis->u32MinDiff)
    14581511        pThis->u32MinDiff = u32MicroDiff;
     
    14651518
    14661519//    Log3(("%s vnetR3TxTimer: Expired\n", INSTANCE(pThis)));
    1467     vnetR3TransmitPendingPackets(pThis, pThis->pTxQueue, false /*fOnWorkerThread*/);
    1468     if (RT_FAILURE(vnetR3CsEnter(pThis, VERR_SEM_BUSY)))
     1520    vnetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, pThisCC->pTxQueue, false /*fOnWorkerThread*/);
     1521    if (RT_FAILURE(vnetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY)))
    14691522    {
    14701523        LogRel(("vnetR3TxTimer: Failed to enter critical section!/n"));
    14711524        return;
    14721525    }
    1473     vringSetNotification(&pThis->VPCI, &pThis->pTxQueue->VRing, true);
    1474     vnetR3CsLeave(pThis);
    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
     1530DECLINLINE(int) vnetR3CreateTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC)
     1531{
     1532    RT_NOREF(pDevIns, pThis, pThisCC);
    14801533    return VINF_SUCCESS;
    14811534}
    14821535
    1483 DECLINLINE(void) vnetR3DestroyTxThreadAndEvent(PVNETSTATE pThis)
    1484 {
    1485     RT_NOREF(pThis);
     1536DECLINLINE(void) vnetR3DestroyTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC)
     1537{
     1538    RT_NOREF(pDevIns, pThis, pThisCC);
    14861539}
    14871540
    14881541# else /* !VNET_TX_DELAY */
    14891542
     1543/**
     1544 * @callback_method_impl{FNPDMTHREADDEV}
     1545 */
    14901546static DECLCALLBACK(int) vnetR3TxThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    14911547{
    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);
    14951550
    14961551    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
    14971552        return VINF_SUCCESS;
    14981553
     1554    int rc = VINF_SUCCESS;
    14991555    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    15001556    {
     
    15051561        while (true)
    15061562        {
    1507             vnetR3TransmitPendingPackets(pThis, 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?
    15081564            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))
    15111567                break;
    1512             vringSetNotification(&pThis->VPCI, &pThis->pTxQueue->VRing, false);
     1568            vringSetNotification(pDevIns, &pThisCC->pTxQueue->VRing, false);
    15131569        }
    15141570    }
     
    15181574
    15191575/**
    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}
    15251577 */
    15261578static DECLCALLBACK(int) vnetR3TxThreadWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    15271579{
    1528     PVNETSTATE pThis = (PVNETSTATE)pThread->pvUser;
     1580    PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);
     1581    RT_NOREF(pThread);
    15291582    return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hTxEvent);
    15301583}
    15311584
    1532 static int vnetR3CreateTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis)
     1585static int vnetR3CreateTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC)
    15331586{
    15341587    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
     1600static void vnetR3DestroyTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC)
     1601{
     1602    if (pThisCC->pTxThread)
     1603    {
     1604        /* Destroy the thread. */
    15491605        int rcThread;
    1550         /* Destroy the thread. */
    1551         int rc = PDMR3ThreadDestroy(pThis->pTxThread, &rcThread);
     1606        int rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->pTxThread, &rcThread);
    15521607        if (RT_FAILURE(rc) || RT_FAILURE(rcThread))
    15531608            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
    15561612    if (pThis->hTxEvent != NIL_SUPSEMEVENT)
    15571613    {
     
    15611617}
    15621618
    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 */
     1622static DECLCALLBACK(void) vnetR3QueueTransmit(PPDMDEVINS pDevIns, PVQUEUE pQueue)
     1623{
     1624    PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);
    15661625
    15671626    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);
    15701630}
    15711631
    15721632# endif /* !VNET_TX_DELAY */
    15731633
    1574 static uint8_t vnetR3ControlRx(PVNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)
     1634static uint8_t vnetR3ControlRx(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETSTATECC pThisCC,
     1635                               PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)
    15751636{
    15761637    uint8_t u8Ack = VNET_OK;
    15771638    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));
    15811640    Log(("%s vnetR3ControlRx: uCommand=%u fOn=%u\n", INSTANCE(pThis), pCtlHdr->u8Command, fOn));
    15821641    switch (pCtlHdr->u8Command)
     
    15911650            u8Ack = VNET_ERROR;
    15921651    }
    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,
    15951654            (pThis->fPromiscuous | pThis->fAllMulti));
    15961655
     
    15981657}
    15991658
    1600 static uint8_t vnetR3ControlMac(PVNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)
     1659static uint8_t vnetR3ControlMac(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)
    16011660{
    16021661    uint32_t nMacs = 0;
    16031662
    1604     if (pCtlHdr->u8Command != VNET_CTRL_CMD_MAC_TABLE_SET
     1663    if (   pCtlHdr->u8Command != VNET_CTRL_CMD_MAC_TABLE_SET
    16051664        || pElem->nOut != 3
    16061665        || pElem->aSegsOut[1].cb < sizeof(nMacs)
     
    16131672
    16141673    /* 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));
    16181675
    16191676    if (pElem->aSegsOut[1].cb < nMacs * sizeof(RTMAC) + sizeof(nMacs))
     
    16321689    {
    16331690        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
    16391694        Log(("%s vnetR3ControlMac: unicast macs:\n", INSTANCE(pThis)));
    16401695        for(unsigned i = 0; i < nMacs; i++)
    16411696            Log(("         %RTmac\n", &pThis->aMacFilter[i]));
    1642 #endif /* DEBUG */
     1697#endif
    16431698    }
    16441699
    16451700    /* 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));
    16491702
    16501703    if (pElem->aSegsOut[2].cb < nMacs * sizeof(RTMAC) + sizeof(nMacs))
     
    16551708    }
    16561709
    1657     if (nMacs > VNET_MAC_FILTER_LEN - pThis->nMacFilterEntries)
     1710    if (nMacs > VNET_MAC_FILTER_LEN - pThis->cMacFilterEntries)
    16581711    {
    16591712        Log(("%s vnetR3ControlMac: MAC table is too big, have to use allmulti mode (nMacs=%u)\n", INSTANCE(pThis), nMacs));
     
    16631716    {
    16641717        if (nMacs)
    1665             PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns),
     1718            PDMDevHlpPhysRead(pDevIns,
    16661719                              pElem->aSegsOut[2].addr + sizeof(nMacs),
    1667                               &pThis->aMacFilter[pThis->nMacFilterEntries],
     1720                              &pThis->aMacFilter[pThis->cMacFilterEntries],
    16681721                              nMacs * sizeof(RTMAC));
    1669 #ifdef DEBUG
     1722#ifdef LOG_ENABLED
    16701723        Log(("%s vnetR3ControlMac: multicast macs:\n", INSTANCE(pThis)));
    16711724        for(unsigned i = 0; i < nMacs; i++)
    16721725            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;
    16761729    }
    16771730
     
    16791732}
    16801733
    1681 static uint8_t vnetR3ControlVlan(PVNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)
     1734static uint8_t vnetR3ControlVlan(PPDMDEVINS pDevIns, PVNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)
    16821735{
    16831736    uint8_t  u8Ack = VNET_OK;
     
    16911744    }
    16921745
    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));
    16961747
    16971748    if (u16Vid >= VNET_MAX_VID)
     
    17191770
    17201771
    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 */
     1775static 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))
    17261782    {
    17271783        if (elem.nOut < 1 || elem.aSegsOut[0].cb < sizeof(VNETCTLHDR))
     
    17451801        {
    17461802            case VNET_CTRL_CLS_RX_MODE:
    1747                 bAck = vnetR3ControlRx(pThis, &CtlHdr, &elem);
     1803                bAck = vnetR3ControlRx(pDevIns, pThis, pThisCC, &CtlHdr, &elem);
    17481804                break;
    17491805            case VNET_CTRL_CLS_MAC:
    1750                 bAck = vnetR3ControlMac(pThis, &CtlHdr, &elem);
     1806                bAck = vnetR3ControlMac(pDevIns, pThis, &CtlHdr, &elem);
    17511807                break;
    17521808            case VNET_CTRL_CLS_VLAN:
    1753                 bAck = vnetR3ControlVlan(pThis, &CtlHdr, &elem);
     1809                bAck = vnetR3ControlVlan(pDevIns, pThis, &CtlHdr, &elem);
    17541810                break;
    17551811            default:
     
    17591815        PDMDevHlpPCIPhysWrite(pDevIns, elem.aSegsIn[elem.nIn - 1].addr, &bAck, sizeof(bAck));
    17601816
    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 */
     1827static 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);
    17641832}
    17651833
     
    18191887
    18201888    /* Save the common part */
    1821     int rc = vpciSaveExec(&pThis->VPCI, pSSM);
     1889    int rc = vpciR3SaveExec(pHlp, &pThis->VPCI, pSSM);
    18221890    AssertRCReturn(rc, rc);
    18231891
     
    18261894    pHlp->pfnSSMPutBool(    pSSM, pThis->fPromiscuous);
    18271895    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));
    18301898    rc = pHlp->pfnSSMPutMem(pSSM, pThis->aVlanFilter, sizeof(pThis->aVlanFilter));
    18311899    AssertRCReturn(rc, rc);
     
    18581926{
    18591927    PVNETSTATE      pThis   = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);
     1928    PVNETSTATECC    pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC);
    18601929    PCPDMDEVHLPR3   pHlp    = pDevIns->pHlpR3;
    18611930
     
    18681937        LogRel(("%s: The mac address differs: config=%RTmac saved=%RTmac\n", INSTANCE(pThis), &pThis->macConfigured, &macConfigured));
    18691938
    1870     rc = vpciLoadExec(&pThis->VPCI, pSSM, uVersion, uPass, VNET_N_QUEUES);
     1939    rc = vpciR3LoadExec(pHlp, &pThis->VPCI, pSSM, uVersion, uPass, VNET_N_QUEUES);
    18711940    AssertRCReturn(rc, rc);
    18721941
     
    18801949            pHlp->pfnSSMGetBool(pSSM, &pThis->fPromiscuous);
    18811950            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));
    18841953
    18851954            /* 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],
    18881957                       0,
    1889                        (VNET_MAC_FILTER_LEN - pThis->nMacFilterEntries) * sizeof(RTMAC));
     1958                       (VNET_MAC_FILTER_LEN - pThis->cMacFilterEntries) * sizeof(RTMAC));
    18901959            rc = pHlp->pfnSSMGetMem(pSSM, pThis->aVlanFilter, sizeof(pThis->aVlanFilter));
    18911960            AssertRCReturn(rc, rc);
     
    18951964            pThis->fPromiscuous = true;
    18961965            pThis->fAllMulti = false;
    1897             pThis->nMacFilterEntries = 0;
     1966            pThis->cMacFilterEntries = 0;
    18981967            memset(pThis->aMacFilter, 0, VNET_MAC_FILTER_LEN * sizeof(RTMAC));
    18991968            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);
    19021971        }
    19031972    }
     
    19131982static DECLCALLBACK(int) vnetR3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    19141983{
     1984    PVNETSTATE      pThis   = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);
     1985    PVNETSTATECC    pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC);
    19151986    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));
    19211990    /*
    19221991     * Indicate link down to the guest OS that all network connections have
     
    19241993     */
    19251994    if (!PDMDevHlpVMTeleportedAndNotFullyResumedYet(pDevIns))
    1926         vnetR3TempLinkDown(pThis);
     1995        vnetR3TempLinkDown(pDevIns, pThis, pThisCC);
    19271996
    19281997    return VINF_SUCCESS;
     
    19301999
    19312000
    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_SUPPORT
    1955     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 #endif
    1964     AssertRC(rc);
    1965     return rc;
    1966 }
    1967 
    1968 
    19692001/* -=-=-=-=- PDMDEVREG -=-=-=-=- */
    19702002
     
    19742006static DECLCALLBACK(void) vnetR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    19752007{
     2008    PVNETSTATE      pThis   = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);
     2009    PVNETSTATECC    pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC);
     2010    Log(("%s vnetR3Detach:\n", INSTANCE(pThis)));
    19762011    RT_NOREF(fFlags);
    1977     PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);
    1978     Log(("%s vnetR3Detach:\n", INSTANCE(pThis)));
    19792012
    19802013    AssertLogRelReturnVoid(iLUN == 0);
    19812014
    1982     int rc = vnetR3CsEnter(pThis, VERR_SEM_BUSY);
     2015    int rc = vnetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY);
    19832016    if (RT_FAILURE(rc))
    19842017    {
     
    19872020    }
    19882021
    1989     vnetR3DestroyTxThreadAndEvent(pDevIns, pThis);
     2022    vnetR3DestroyTxThreadAndEvent(pDevIns, pThis, pThisCC);
    19902023
    19912024    /*
    19922025     * Zero important members.
    19932026     */
    1994     pThis->pDrvBase = NULL;
    1995     pThis->pDrv = NULL;
    1996 
    1997     vnetR3CsLeave(pThis);
     2027    pThisCC->pDrvBase = NULL;
     2028    pThisCC->pDrv    = NULL;
     2029
     2030    vnetR3CsLeave(pDevIns, pThis);
    19982031}
    19992032
     
    20042037static DECLCALLBACK(int) vnetR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    20052038{
     2039    PVNETSTATE      pThis   = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);
     2040    PVNETSTATECC    pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC);
    20062041    RT_NOREF(fFlags);
    2007     PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);
    20082042    LogFlow(("%s vnetR3Attach:\n",  INSTANCE(pThis)));
    20092043
    20102044    AssertLogRelReturn(iLUN == 0, VERR_PDM_NO_SUCH_LUN);
    20112045
    2012     int rc = vnetR3CsEnter(pThis, VERR_SEM_BUSY);
     2046    int rc = vnetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY);
    20132047    if (RT_FAILURE(rc))
    20142048    {
     
    20202054     * Attach the driver.
    20212055     */
    2022     rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->VPCI.IBase, &pThis->pDrvBase, "Network Port");
     2056    rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThisCC->VPCI.IBase, &pThisCC->pDrvBase, "Network Port");
    20232057    if (RT_SUCCESS(rc))
    20242058    {
     
    20332067#endif
    20342068        }
    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"),
    20372071                      rc = VERR_PDM_MISSING_INTERFACE_BELOW);
    20382072
    2039         vnetR3CreateTxThreadAndEvent(pDevIns, pThis);
     2073        vnetR3CreateTxThreadAndEvent(pDevIns, pThis, pThisCC);
    20402074    }
    20412075    else if (   rc == VERR_PDM_NO_ATTACHED_DRIVER
     
    20532087     */
    20542088    if (RT_SUCCESS(rc))
    2055         vnetR3TempLinkDown(pThis);
    2056 
    2057     vnetR3CsLeave(pThis);
     2089        vnetR3TempLinkDown(pDevIns, pThis, pThisCC);
     2090
     2091    vnetR3CsLeave(pDevIns, pThis);
    20582092    return rc;
    2059 
    20602093}
    20612094
     
    20782111    /* Poke thread waiting for buffer space. */
    20792112    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_DELAY
    2090     PVNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);
    2091     pThis->pTxTimerRC = TMTimerRCPtr(pThis->pTxTimerR3);
    2092 #endif
    20932113}
    20942114
     
    21172137    //     PDMR3CritSectDelete(&pThis->csRx);
    21182138
    2119     return vpciDestruct(&pThis->VPCI);
     2139    return vpciR3Term(pDevIns, &pThis->VPCI);
    21202140}
    21212141
     
    21282148    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
    21292149    PVNETSTATE      pThis   = PDMDEVINS_2_DATA(pDevIns, PVNETSTATE);
     2150    PVNETSTATECC    pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVNETSTATECC);
    21302151    PCPDMDEVHLPR3   pHlp    = pDevIns->pHlpR3;
    21312152    int             rc;
     
    21342155     * Initialize the instance data suffiencently for the destructor not to blow up.
    21352156     */
    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;
    21372160#ifndef VNET_TX_DELAY
    2138     pThis->hTxEvent              = NIL_SUPSEMEVENT;
    2139     pThis->pTxThread             = NULL;
     2161    pThis->hTxEvent                 = NIL_SUPSEMEVENT;
     2162    pThisCC->pTxThread              = NULL;
    21402163#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
    21412178
    21422179    /* Do our own locking. */
     
    21442181    AssertRCReturn(rc, rc);
    21452182
    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);
    21502189    AssertRCReturn(rc, rc);
    21512190
    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);
    21552195
    21562196    Log(("%s Constructing new instance\n", INSTANCE(pThis)));
     
    21822222    pThis->config.uStatus = 0;
    21832223
    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 
    21972224    /* Initialize critical section. */
    21982225    // char szTmp[sizeof(pThis->VPCI.szInstance) + 2];
     
    22032230
    22042231    /* 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);
    22062235    AssertRCReturn(rc, rc);
    22072236
     
    22142243
    22152244    /* Create Link Up Timer */
    2216     rc = PDMDevHlpTMTimerCreate(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);
    22182247    AssertRCReturn(rc, rc);
    22192248
    22202249#ifdef VNET_TX_DELAY
    22212250    /* Create Transmit Delay Timer */
    2222     rc = PDMDevHlpTMTimerCreate(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);
    22242253    AssertRCReturn(rc, rc);
    2225     pThis->pTxTimerR0 = TMTimerR0Ptr(pThis->pTxTimerR3);
    2226     pThis->pTxTimerRC = TMTimerRCPtr(pThis->pTxTimerR3);
    22272254
    22282255    pThis->u32i = pThis->u32AvgDiff = pThis->u32MaxDiff = 0;
     
    22302257#endif /* VNET_TX_DELAY */
    22312258
    2232     rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->VPCI.IBase, &pThis->pDrvBase, "Network Port");
     2259    rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThisCC->VPCI.IBase, &pThisCC->pDrvBase, "Network Port");
    22332260    if (RT_SUCCESS(rc))
    22342261    {
     
    22382265                                       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"));
    22392266        }
    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"),
    22422269                        VERR_PDM_MISSING_INTERFACE_BELOW);
    22432270
    2244         vnetR3CreateTxThreadAndEvent(pDevIns, pThis);
     2271        vnetR3CreateTxThreadAndEvent(pDevIns, pThis, pThisCC);
    22452272    }
    22462273    else if (   rc == VERR_PDM_NO_ATTACHED_DRIVER
     
    22562283    AssertRCReturn(rc, rc);
    22572284
    2258     rc = vnetIoCb_Reset(&pThis->VPCI);
     2285    ASMCompilerBarrier(); /* paranoia */
     2286    rc = vnetIoCb_Reset(pDevIns);
    22592287    AssertRCReturn(rc, rc);
    22602288
     2289    /*
     2290     * Statistics and debug stuff.
     2291     */
    22612292    PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatReceiveBytes,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,          "Amount of data received",            "/Public/Net/VNet%u/BytesReceived", iInstance);
    22622293    PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitBytes,      STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,          "Amount of data transmitted",         "/Public/Net/VNet%u/BytesTransmitted", iInstance);
     
    22792310# endif
    22802311
     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
    22812316    return VINF_SUCCESS;
    22822317}
    22832318
    2284 #endif /* IN_RING3 */
     2319#else  /* !IN_RING3 */
     2320
     2321/**
     2322 * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
     2323 */
     2324static 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 */
    22852340
    22862341/**
     
    22922347    /* .uReserved0 = */             0,
    22932348    /* .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,
    22992350    /* .fClass = */                 PDM_DEVREG_CLASS_NETWORK,
    23002351    /* .cMaxInstances = */          ~0U,
    23012352    /* .uSharedVersion = */         42,
    23022353    /* .cbInstanceShared = */       sizeof(VNETSTATE),
    2303     /* .cbInstanceCC = */           0,
    2304     /* .cbInstanceRC = */           0,
     2354    /* .cbInstanceCC = */           sizeof(VNETSTATECC),
     2355    /* .cbInstanceRC = */           sizeof(VNETSTATERC),
    23052356    /* .cMaxPciDevices = */         1,
    23062357    /* .cMaxMsixVectors = */        0,
     
    23112362    /* .pfnConstruct = */           vnetR3Construct,
    23122363    /* .pfnDestruct = */            vnetR3Destruct,
    2313     /* .pfnRelocate = */            vnetR3Relocate,
     2364    /* .pfnRelocate = */            NULL,
    23142365    /* .pfnMemSetup = */            NULL,
    23152366    /* .pfnPowerOn = */             NULL,
     
    23332384#elif defined(IN_RING0)
    23342385    /* .pfnEarlyConstruct = */      NULL,
    2335     /* .pfnConstruct = */           NULL,
     2386    /* .pfnConstruct = */           vnetRZConstruct,
    23362387    /* .pfnDestruct = */            NULL,
    23372388    /* .pfnFinalDestruct = */       NULL,
     
    23462397    /* .pfnReserved7 = */           NULL,
    23472398#elif defined(IN_RC)
    2348     /* .pfnConstruct = */           NULL,
     2399    /* .pfnConstruct = */           vnetRZConstruct,
    23492400    /* .pfnReserved0 = */           NULL,
    23502401    /* .pfnReserved1 = */           NULL,
  • trunk/src/VBox/Devices/VirtIO/Virtio.cpp

    r81703 r81720  
    2525#include <iprt/uuid.h>
    2626#include <VBox/vmm/pdmdev.h>
     27#include <VBox/AssertGuest.h>
    2728#include "Virtio.h"
    2829
    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)
    4235
    4336
     
    6861// }
    6962
    70 void vringReadDesc(PVPCISTATE pState, PVRING pVRing, uint32_t uIndex, PVRINGDESC pDesc)
    71 {
    72     //Log(("%s vringReadDesc: ring=%p idx=%u\n", INSTANCE(pState), pVRing, uIndex));
    73     PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns),
     63void 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,
    7467                      pVRing->addrDescriptors + sizeof(VRINGDESC) * (uIndex % pVRing->uSize),
    7568                      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                       pVRing->addrAvail + RT_UOFFSETOF_DYN(VRINGAVAIL, auRing[uIndex % pVRing->uSize]),
     69    /** @todo r=bird: Why exactly are we sometimes using PDMDevHlpPhysRead rather
     70     *        than PDMDevHlpPCIPhysRead? */
     71}
     72
     73uint16_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]),
    8477                      &tmp, sizeof(tmp));
    8578    return tmp;
    8679}
    8780
    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));
     81uint16_t vringReadAvailFlags(PPDMDEVINS pDevIns, PVRING pVRing)
     82{
     83    uint16_t tmp = 0;
     84    PDMDevHlpPhysRead(pDevIns, pVRing->addrAvail + RT_UOFFSETOF(VRINGAVAIL, uFlags), &tmp, sizeof(tmp));
    9585    return tmp;
    9686}
    9787
    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));
     88void 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));
    10592
    10693    if (fEnabled)
    107         tmp &= ~ VRINGUSED_F_NO_NOTIFY;
     94        fState &= ~ VRINGUSED_F_NO_NOTIFY;
    10895    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
     101bool vqueueSkip(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue)
     102{
     103    if (vqueueIsEmpty(pDevIns, pQueue))
    119104        return false;
    120105
    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));
    123107    pQueue->uNextAvailIndex++;
    124108    return true;
    125109}
    126110
    127 bool vqueueGet(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove)
    128 {
    129     if (vqueueIsEmpty(pState, pQueue))
     111bool vqueueGet(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove)
     112{
     113    if (vqueueIsEmpty(pDevIns, pQueue))
    130114        return false;
    131115
    132116    pElem->nIn = pElem->nOut = 0;
    133117
    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));
    136119
    137120    VRINGDESC desc;
    138     uint16_t  idx = vringReadAvail(pState, &pQueue->VRing, pQueue->uNextAvailIndex);
     121    uint16_t  idx = vringReadAvail(pDevIns, &pQueue->VRing, pQueue->uNextAvailIndex);
    139122    if (fRemove)
    140123        pQueue->uNextAvailIndex++;
     
    157140            {
    158141                LogRel(("%s: too many linked descriptors; check if the guest arranges descriptors in a loop.\n",
    159                         INSTANCE(pState)));
     142                        INSTANCE(pThis)));
    160143                if (ASMAtomicReadU32(&s_cMessages) != 1)
    161144                    LogRel(("%s: (the above error has occured %u times so far)\n",
    162                             INSTANCE(pState), ASMAtomicReadU32(&s_cMessages)));
     145                            INSTANCE(pThis), ASMAtomicReadU32(&s_cMessages)));
    163146                ASMAtomicWriteU32(&s_cThreshold, ASMAtomicReadU32(&s_cThreshold) * 10);
    164147            }
     
    167150        RT_UNTRUSTED_VALIDATED_FENCE();
    168151
    169         vringReadDesc(pState, &pQueue->VRing, idx, &desc);
     152        vringReadDesc(pDevIns, &pQueue->VRing, idx, &desc);
    170153        if (desc.u16Flags & VRINGDESC_F_WRITE)
    171154        {
    172             Log2(("%s vqueueGet: %s IN  seg=%u desc_idx=%u addr=%p cb=%u\n", INSTANCE(pState),
    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));
    174157            pSeg = &pElem->aSegsIn[pElem->nIn++];
    175158        }
    176159        else
    177160        {
    178             Log2(("%s vqueueGet: %s OUT seg=%u desc_idx=%u addr=%p cb=%u\n", INSTANCE(pState),
    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));
    180163            pSeg = &pElem->aSegsOut[pElem->nOut++];
    181164        }
     
    188171    } while (desc.u16Flags & VRINGDESC_F_NEXT);
    189172
    190     Log2(("%s vqueueGet: %s head_desc_idx=%u nIn=%u nOut=%u\n", INSTANCE(pState),
    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));
    192175    return true;
    193176}
    194177
    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
     179static 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));
    201183    return tmp;
    202184}
    203 
    204 void vringWriteUsedIndex(PVPCISTATE pState, PVRING pVRing, uint16_t u16Value)
    205 {
    206     PDMDevHlpPCIPhysWrite(pState->CTX_SUFF(pDevIns),
     185#endif
     186
     187static void vringWriteUsedIndex(PPDMDEVINS pDevIns, PVRING pVRing, uint16_t u16Value)
     188{
     189    PDMDevHlpPCIPhysWrite(pDevIns,
    207190                          pVRing->addrUsed + RT_UOFFSETOF(VRINGUSED, uIndex),
    208191                          &u16Value, sizeof(u16Value));
    209192}
    210193
    211 void vringWriteUsedElem(PVPCISTATE pState, PVRING pVRing, uint32_t uIndex, uint32_t uId, uint32_t uLen)
     194static void vringWriteUsedElem(PPDMDEVINS pDevIns, PVRING pVRing, uint32_t uIndex, uint32_t uId, uint32_t uLen)
    212195{
    213196    VRINGUSEDELEM elem;
     
    215198    elem.uId = uId;
    216199    elem.uLen = uLen;
    217     PDMDevHlpPCIPhysWrite(pState->CTX_SUFF(pDevIns),
     200    PDMDevHlpPCIPhysWrite(pDevIns,
    218201                          pVRing->addrUsed + RT_UOFFSETOF_DYN(VRINGUSED, aRing[uIndex % pVRing->uSize]),
    219202                          &elem, sizeof(elem));
     
    221204
    222205
    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));
     206void 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));
    230209
    231210    Assert(uReserved < uTotalLen);
     
    252231        if (pElem->aSegsIn[i].pv != NULL)
    253232        {
    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,
    262237                                  pElem->aSegsIn[i].addr + cbSkip,
    263238                                  pElem->aSegsIn[i].pv,
     
    269244    }
    270245
    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,
    278250                       pQueue->uNextUsedIndex++,
    279251                       pElem->uIndex, uTotalLen);
     
    281253
    282254
    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);
     255void 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);
    293264        if (RT_FAILURE(rc))
    294             Log(("%s vqueueNotify: Failed to raise an interrupt (%Rrc).\n", INSTANCE(pState), rc));
     265            Log(("%s vqueueNotify: Failed to raise an interrupt (%Rrc).\n", INSTANCE(pThis), rc));
    295266    }
    296267    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
     272void 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);
    309278}
    310279
     
    313282 * Raise interrupt.
    314283 *
    315  * @param   pState      The device state structure.
     284 * @param   pDevIns     The device instance.
     285 * @param   pThis       The shared virtio core instance data.
    316286 * @param   rcBusy      Status code to return when the critical section is busy.
    317287 * @param   u8IntCause  Interrupt cause bit mask to set in PCI ISR port.
    318288 */
    319 int vpciRaiseInterrupt(VPCISTATE *pState, int rcBusy, uint8_t u8IntCause)
     289int vpciRaiseInterrupt(PPDMDEVINS pDevIns, PVPCISTATE pThis, int rcBusy, uint8_t u8IntCause)
    320290{
    321291    RT_NOREF_PV(rcBusy);
    322     // int rc = vpciCsEnter(pState, rcBusy);
     292    // int rc = vpciCsEnter(pThis, rcBusy);
    323293    // if (RT_UNLIKELY(rc != VINF_SUCCESS))
    324294    //     return rc;
    325295
    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);
    333302    return VINF_SUCCESS;
    334303}
     
    337306 * Lower interrupt.
    338307 *
    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 */
     311static 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
     319void vpciReset(PPDMDEVINS pDevIns, PVPCISTATE pThis)
    349320{
    350321    /* No interrupts should survive device reset, see @bugref(9556). */
    351     if (pState->uISR)
    352         vpciLowerInterrupt(pState);
    353 
    354     pState->uGuestFeatures = 0;
    355     pState->uQueueSelector = 0;
    356     pState->uStatus        = 0;
    357     pState->uISR           = 0;
    358 
    359     for (unsigned i = 0; i < pState->nQueues; i++)
    360         vqueueReset(&pState->Queues[i]);
    361 }
    362 
    363 
    364 DECLINLINE(uint32_t) vpciGetHostFeatures(PVPCISTATE pState, PCVPCIIOCALLBACKS  pCallbacks)
    365 {
    366     return pCallbacks->pfnGetHostFeatures(pState)
     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
     335DECLINLINE(uint32_t) vpciGetHostFeatures(PVPCISTATE pThis, PCVPCIIOCALLBACKS  pCallbacks)
     336{
     337    return pCallbacks->pfnGetHostFeatures(pThis)
    367338        | VPCI_F_NOTIFY_ON_EMPTY;
    368339}
     
    374345 *
    375346 * @param   pDevIns     The device instance.
    376  * @param   pState      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.
    378349 * @param   pu32        Where to store the result.
    379350 * @param   cb          Number of bytes read.
     
    382353 */
    383354int vpciIOPortIn(PPDMDEVINS         pDevIns,
    384                  PVPCISTATE         pState,
    385                  RTIOPORT           Port,
     355                 PVPCISTATE         pThis,
     356                 RTIOPORT           offPort,
    386357                 uint32_t          *pu32,
    387358                 unsigned           cb,
    388359                 PCVPCIIOCALLBACKS  pCallbacks)
    389360{
    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);
    392362
    393363    /*
     
    400370     * holding cs transmitting queued packets.
    401371     *
    402     rc = vpciCsEnter(pState, VINF_IOM_R3_IOPORT_READ);
     372    int rc = vpciCsEnter(pThis, VINF_IOM_R3_IOPORT_READ);
    403373    if (RT_UNLIKELY(rc != VINF_SUCCESS))
    404374    {
    405         STAM_PROFILE_ADV_STOP(&pState->CTX_SUFF(StatIORead), a);
     375        STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF(StatIORead), a);
    406376        return rc;
    407377        }*/
    408 
    409     Port -= pState->IOPortBase;
    410     switch (Port)
     378    int rc = VINF_SUCCESS;
     379
     380    switch (offPort)
    411381    {
    412382        case VPCI_HOST_FEATURES:
    413383            /* 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;
    415386            break;
    416387
    417388        case VPCI_GUEST_FEATURES:
    418             *pu32 = pState->uGuestFeatures;
     389            ASSERT_GUEST_MSG(cb == 4, ("%d\n", cb));
     390            *pu32 = pThis->uGuestFeatures;
    419391            break;
    420392
    421393        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;
    423396            break;
    424397
    425398        case VPCI_QUEUE_NUM:
    426             Assert(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;
    428401            break;
    429402
    430403        case VPCI_QUEUE_SEL:
    431             Assert(cb == 2);
    432             *(uint16_t*)pu32 = pState->uQueueSelector;
     404            ASSERT_GUEST_MSG(cb == 2, ("%d\n", cb));
     405            *pu32 = pThis->uQueueSelector;
    433406            break;
    434407
    435408        case VPCI_STATUS:
    436             Assert(cb == 1);
    437             *(uint8_t*)pu32 = pState->uStatus;
     409            ASSERT_GUEST_MSG(cb == 1, ("%d\n", cb));
     410            *pu32 = pThis->uStatus;
    438411            break;
    439412
    440413        case VPCI_ISR:
    441             Assert(cb == 1);
    442             *(uint8_t*)pu32 = pState->uISR;
    443             pState->uISR = 0; /* read clears all interrupts */
    444             vpciLowerInterrupt(pState);
     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);
    445418            break;
    446419
    447420        default:
    448             if (Port >= VPCI_CONFIG)
    449                 rc = pCallbacks->pfnGetConfig(pState, Port - VPCI_CONFIG, cb, pu32);
     421            if (offPort >= VPCI_CONFIG)
     422                rc = pCallbacks->pfnGetConfig(pThis, offPort - VPCI_CONFIG, cb, pu32);
    450423            else
    451424            {
    452                 *pu32 = 0xFFFFFFFF;
     425                *pu32 = UINT32_MAX;
    453426                rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "%s vpciIOPortIn: no valid port at offset port=%RTiop cb=%08x\n",
    454                                        INSTANCE(pState), Port, cb);
     427                                       INSTANCE(pThis), offPort, cb);
    455428            }
    456429            break;
    457430    }
    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);
    461436    return rc;
    462437}
     
    469444 *
    470445 * @param   pDevIns     The device instance.
    471  * @param   pState      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.
    473448 * @param   u32         The value to output.
    474449 * @param   cb          The value size in bytes.
     
    477452 */
    478453int vpciIOPortOut(PPDMDEVINS         pDevIns,
    479                   PVPCISTATE         pState,
    480                   RTIOPORT           Port,
     454                  PVPCISTATE         pThis,
     455                  PVPCISTATECC       pThisCC,
     456                  RTIOPORT           offPort,
    481457                  uint32_t           u32,
    482458                  unsigned           cb,
    483459                  PCVPCIIOCALLBACKS  pCallbacks)
    484460{
    485     STAM_PROFILE_ADV_START(&pState->CTX_SUFF(StatIOWrite), a);
     461    STAM_PROFILE_ADV_START(&pThis->CTX_SUFF(StatIOWrite), a);
    486462    int  rc = VINF_SUCCESS;
    487463    bool fHasBecomeReady;
    488464
    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)
    493468    {
    494469        case VPCI_GUEST_FEATURES:
    495470        {
    496             const uint32_t fHostFeatures = vpciGetHostFeatures(pState, pCallbacks);
     471            const uint32_t fHostFeatures = vpciGetHostFeatures(pThis, pCallbacks);
    497472
    498473            if (RT_LIKELY((u32 & ~fHostFeatures) == 0))
    499             {
    500                 pState->uGuestFeatures = u32;
    501             }
     474                pThis->uGuestFeatures = u32;
    502475            else
    503476            {
     
    510483                {
    511484                    Log(("%s WARNING! Guest failed to negotiate properly (guest=%x)\n",
    512                          INSTANCE(pState), u32));
    513                     pState->uGuestFeatures = pCallbacks->pfnGetHostMinimalFeatures(pState);
     485                         INSTANCE(pThis), u32));
     486                    pThis->uGuestFeatures = pCallbacks->pfnGetHostMinimalFeatures(pThis);
    514487                }
    515488                else
    516489                {
    517490                    Log(("%s Guest asked for features host does not support! (host=%x guest=%x)\n",
    518                          INSTANCE(pState), fHostFeatures, u32));
    519                     pState->uGuestFeatures = u32 & fHostFeatures;
     491                         INSTANCE(pThis), fHostFeatures, u32));
     492                    pThis->uGuestFeatures = u32 & fHostFeatures;
    520493                }
    521494            }
    522             pCallbacks->pfnSetHostFeatures(pState, pState->uGuestFeatures);
     495            pCallbacks->pfnSetHostFeatures(pThis, pThis->uGuestFeatures);
    523496            break;
    524497        }
     
    531504             * VIRTIO_PCI_QUEUE_NUM.
    532505             */
    533             pState->Queues[pState->uQueueSelector].uPageNumber = u32;
     506            pThis->Queues[pThis->uQueueSelector].uPageNumber = u32;
    534507            if (u32)
    535                 vqueueInit(&pState->Queues[pState->uQueueSelector], u32);
     508                vqueueInit(&pThis->Queues[pThis->uQueueSelector], u32);
    536509            else
    537                 rc = pCallbacks->pfnReset(pState);
     510                rc = pCallbacks->pfnReset(pDevIns);
    538511            break;
    539512
    540513        case VPCI_QUEUE_SEL:
    541             Assert(cb == 2);
     514            ASSERT_GUEST_MSG(cb == 2, ("cb=%u\n", cb));
    542515            u32 &= 0xFFFF;
    543             if (u32 < pState->nQueues)
    544                 pState->uQueueSelector = u32;
     516            if (u32 < pThis->cQueues)
     517                pThis->uQueueSelector = u32;
    545518            else
    546                 Log3(("%s vpciIOPortOut: Invalid queue selector %08x\n", INSTANCE(pState), u32));
     519                Log3(("%s vpciIOPortOut: Invalid queue selector %08x\n", INSTANCE(pThis), u32));
    547520            break;
    548521
    549522        case VPCI_QUEUE_NOTIFY:
    550523#ifdef IN_RING3
    551             Assert(cb == 2);
     524            ASSERT_GUEST_MSG(cb == 2, ("cb=%u\n", cb));
    552525            u32 &= 0xFFFF;
    553             if (u32 < pState->nQueues)
     526            if (u32 < pThis->cQueues)
    554527            {
    555528                RT_UNTRUSTED_VALIDATED_FENCE();
    556                 if (pState->Queues[u32].VRing.addrDescriptors)
     529                if (pThis->Queues[u32].VRing.addrDescriptors)
    557530                {
    558                     // rc = vpciCsEnter(pState, VERR_SEM_BUSY);
     531
     532                    // rc = vpciCsEnter(pThis, VERR_SEM_BUSY);
    559533                    // if (RT_LIKELY(rc == VINF_SUCCESS))
    560534                    // {
    561                         pState->Queues[u32].pfnCallback(pDevIns, pState, &pState->Queues[u32]);
    562                     //     vpciCsLeave(pState);
     535                        pThisCC->Queues[u32].pfnCallback(pDevIns, &pThis->Queues[u32]);
     536                    //     vpciCsLeave(pThis);
    563537                    // }
    564538                }
    565539                else
    566540                    Log(("%s The queue (#%d) being notified has not been initialized.\n",
    567                          INSTANCE(pState), u32));
     541                         INSTANCE(pThis), u32));
    568542            }
    569543            else
    570                 Log(("%s Invalid queue number (%d)\n", INSTANCE(pState), u32));
     544                Log(("%s Invalid queue number (%d)\n", INSTANCE(pThis), u32));
    571545#else
     546            RT_NOREF(pThisCC);
    572547            rc = VINF_IOM_R3_IOPORT_WRITE;
    573548#endif
     
    575550
    576551        case VPCI_STATUS:
    577             Assert(cb == 1);
     552            ASSERT_GUEST_MSG(cb == 1, ("cb=%u\n", cb));
    578553            u32 &= 0xFF;
    579             fHasBecomeReady = !(pState->uStatus & VPCI_STATUS_DRV_OK) && (u32 & VPCI_STATUS_DRV_OK);
    580             pState->uStatus = u32;
     554            fHasBecomeReady = !(pThis->uStatus & VPCI_STATUS_DRV_OK) && (u32 & VPCI_STATUS_DRV_OK);
     555            pThis->uStatus = u32;
    581556            /* Writing 0 to the status port triggers device reset. */
    582557            if (u32 == 0)
    583                 rc = pCallbacks->pfnReset(pState);
     558                rc = pCallbacks->pfnReset(pDevIns);
    584559            else if (fHasBecomeReady)
    585560            {
     
    592567                PDMPciDevSetCommand(pPciDev, PDMPciDevGetCommand(pPciDev) | PCI_COMMAND_BUSMASTER);
    593568
    594                 pCallbacks->pfnReady(pState);
     569                pCallbacks->pfnReady(pDevIns);
    595570            }
    596571            break;
    597572
    598573        default:
    599             if (Port >= VPCI_CONFIG)
    600                 rc = pCallbacks->pfnSetConfig(pState, Port - VPCI_CONFIG, cb, &u32);
     574            if (offPort >= VPCI_CONFIG)
     575                rc = pCallbacks->pfnSetConfig(pThis, offPort - VPCI_CONFIG, cb, &u32);
    601576            else
    602                 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "%s vpciIOPortOut: no valid port at offset Port=%RTiop cb=%08x\n",
    603                                        INSTANCE(pState), 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);
    604579            break;
    605580    }
    606581
    607     STAM_PROFILE_ADV_STOP(&pState->CTX_SUFF(StatIOWrite), a);
     582    STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF(StatIOWrite), a);
    608583    return rc;
    609584}
     
    612587
    613588/**
    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 */
     591void *vpciR3QueryInterface(PVPCISTATECC pThisCC, const char *pszIID)
     592{
     593    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThisCC->IBase);
     594    PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThisCC->ILeds);
    623595    return NULL;
    624596}
    625597
    626598/**
    627  * Gets the pointer to the status LED of a unit.
     599 * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed}
     600 */
     601static 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.
    628614 *
    629615 * @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 */
     619void 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.
    650630 *
    651631 * @returns VBox status code.
    652  * @param   pState          Pointer to the device state structure.
     632 * @param   pThis          Pointer to the device state structure.
    653633 * @param   fOn             New LED state.
    654634 */
    655 void vpciSetWriteLed(PVPCISTATE pState, bool fOn)
    656 {
    657     LogFlow(("%s vpciSetWriteLed: %s\n", INSTANCE(pState), fOn?"on":"off"));
     635void vpciR3SetReadLed(PVPCISTATE pThis, bool fOn)
     636{
     637    LogFlow(("%s vpciR3SetReadLed: %s\n", INSTANCE(pThis), fOn?"on":"off"));
    658638    if (fOn)
    659         pState->led.Asserted.s.fWriting = pState->led.Actual.s.fWriting = 1;
     639        pThis->led.Asserted.s.fReading = pThis->led.Actual.s.fReading = 1;
    660640    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 */
    682646/**
    683647 * Sets 32-bit register in PCI configuration space.
     
    692656    *(uint32_t*)&refPciDev.config[uOffset] = u32Value;
    693657}
    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 */
     664void 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
     698void 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.
    735712 *
    736713 * @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.
    738716 * @param   pSSM        The handle to the saved state.
    739717 */
    740 int vpciSaveExec(PVPCISTATE pState, PSSMHANDLE pSSM)
    741 {
    742     int rc;
    743 
    744     vpciDumpState(pState, "vpciSaveExec");
    745 
    746     rc = SSMR3PutU32(pSSM, pState->uGuestFeatures);
     718int 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);
    747729    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);
    767736        AssertRCReturn(rc, rc);
    768737    }
     
    775744 *
    776745 * @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.
    778748 * @param   pSSM        The handle to the saved state.
    779749 * @param   uVersion    The data unit version number.
    780750 * @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 */
     753int vpciR3LoadExec(PCPDMDEVHLPR3 pHlp, PVPCISTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t cQueues)
    783754{
    784755    int rc;
     
    787758    {
    788759        /* 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);
    797764
    798765        /* Restore queues */
    799766        if (uVersion > VIRTIO_SAVEDSTATE_VERSION_3_1_BETA1)
    800767        {
    801             rc = SSMR3GetU32(pSSM, &pState->nQueues);
     768            rc = pHlp->pfnSSMGetU32(pSSM, &pThis->cQueues);
    802769            AssertRCReturn(rc, rc);
    803770        }
    804771        else
    805             pState->nQueues = nQueues;
    806         AssertLogRelMsgReturn(pState->nQueues <= VIRTIO_MAX_NQUEUES, ("%#x\n", pState->nQueues), VERR_SSM_LOAD_CONFIG_MISMATCH);
    807         AssertLogRelMsgReturn(pState->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),
    809776                              VERR_SSM_LOAD_CONFIG_MISMATCH);
    810777
    811         for (unsigned i = 0; i < pState->nQueues; i++)
     778        for (unsigned i = 0; i < pThis->cQueues; i++)
    812779        {
    813             rc = SSMR3GetU16(pSSM, &pState->Queues[i].VRing.uSize);
     780            rc = pHlp->pfnSSMGetU16(pSSM, &pThis->Queues[i].VRing.uSize);
    814781            AssertRCReturn(rc, rc);
    815             rc = SSMR3GetU32(pSSM, &pState->Queues[i].uPageNumber);
     782            rc = pHlp->pfnSSMGetU32(pSSM, &pThis->Queues[i].uPageNumber);
    816783            AssertRCReturn(rc, rc);
    817784
    818             if (pState->Queues[i].uPageNumber)
    819                 vqueueInit(&pState->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);
    822789            AssertRCReturn(rc, rc);
    823             rc = SSMR3GetU16(pSSM, &pState->Queues[i].uNextUsedIndex);
     790            rc = pHlp->pfnSSMGetU16(pSSM, &pThis->Queues[i].uNextUsedIndex);
    824791            AssertRCReturn(rc, rc);
    825792        }
    826793    }
    827794
    828     vpciDumpState(pState, "vpciLoadExec");
     795    vpciR3DumpState(pThis, "vpciLoadExec");
    829796
    830797    return VINF_SUCCESS;
     
    839806 * @thread  EMT
    840807 */
    841 static DECLCALLBACK(void) vpciConfigure(PPDMPCIDEV pPciDev,
    842                                         uint16_t uDeviceId,
    843                                         uint16_t uClass)
     808static void vpciConfigure(PPDMPCIDEV pPciDev, uint16_t uDeviceId, uint16_t uClass)
    844809{
    845810    /* Configure PCI Device, assume 32-bit mode ******************************/
     
    857822    PDMPciDevSetByte(pPciDev, VBOX_PCI_INTERRUPT_PIN,       0x01);
    858823
    859 #ifdef VBOX_WITH_MSI_DEVICES
     824# ifdef VBOX_WITH_MSI_DEVICES
    860825    PDMPciDevSetCapabilityList(pPciDev,                     0x80);
    861826    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
     831int 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);
    895841
    896842    /* 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     */
    901849    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
    902850    PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
     851
    903852    /* Set PCI config registers */
    904853    vpciConfigure(pPciDev, uDeviceId, uClass);
     854
    905855    /* Register PCI device */
    906856    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
    912861    {
    913862        PDMMSIREG aMsiReg;
     
    920869        rc = PDMDevHlpPCIRegisterMsi(pDevIns, &aMsiReg);
    921870        if (RT_FAILURE (rc))
    922             PCIDevSetCapabilityList(&pState->pciDevice, 0x0);
     871            PCIDevSetCapabilityList(&pThis->pciDevice, 0x0);
    923872    }
    924 #endif
    925 #endif
    926 
    927     /* Status driver */
     873#  endif
     874# endif
     875
     876    /*
     877     * Attach the status driver (optional).
     878     */
    928879    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)
    931884        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     PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatIOReadR3,           STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO reads in R3",      vpciCounter(pcszNameFmt, "IO/ReadR3"), iInstance);
    938     PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatIOReadR0,           STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO reads in R0",      vpciCounter(pcszNameFmt, "IO/ReadR0"), iInstance);
    939     PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatIOReadRC,           STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO reads in RC",      vpciCounter(pcszNameFmt, "IO/ReadRC"), iInstance);
    940     PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatIOWriteR3,          STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO writes in R3",     vpciCounter(pcszNameFmt, "IO/WriteR3"), iInstance);
    941     PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatIOWriteR0,          STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO writes in R0",     vpciCounter(pcszNameFmt, "IO/WriteR0"), iInstance);
    942     PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatIOWriteRC,          STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO writes in RC",     vpciCounter(pcszNameFmt, "IO/WriteRC"), iInstance);
    943     PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatIntsRaised,         STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,     "Number of raised interrupts",   vpciCounter(pcszNameFmt, "Interrupts/Raised"), iInstance);
    944     PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatIntsSkipped,        STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,     "Number of skipped interrupts",   vpciCounter(pcszNameFmt, "Interrupts/Skipped"), iInstance);
    945     PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatCsR3,               STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling CS wait in R3",      vpciCounter(pcszNameFmt, "Cs/CsR3"), iInstance);
    946     PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatCsR0,               STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling CS wait in R0",      vpciCounter(pcszNameFmt, "Cs/CsR0"), iInstance);
    947     PDMDevHlpSTAMRegisterF(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;
    951904}
    952905
     
    957910 *
    958911 * @returns VBox status code.
    959  * @param   pState      The device state structure.
    960  */
    961 int vpciDestruct(VPCISTATE* pState)
    962 {
    963     Log(("%s Destroying PCI instance\n", INSTANCE(pState)));
    964 
    965     if (PDMCritSectIsInitialized(&pState->cs))
    966         PDMR3CritSectDelete(&pState->cs);
     912 * @param   pThis      The shared virtio core instance data.
     913 */
     914int 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);
    967920
    968921    return VINF_SUCCESS;
    969922}
    970923
    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;
     924PVQUEUE vpciR3AddQueue(PVPCISTATE pThis, PVPCISTATECC pThisCC, unsigned uSize,
     925                       PFNVPCIQUEUECALLBACK pfnCallback, const char *pcszName)
     926{
    998927    /* Find an empty queue slot */
    999     for (unsigned i = 0; i < pState->nQueues; i++)
    1000     {
    1001         if (pState->Queues[i].VRing.uSize == 0)
     928    for (unsigned i = 0; i < pThis->cQueues; i++)
     929    {
     930        if (pThis->Queues[i].VRing.uSize == 0)
    1002931        {
    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;
    1005940        }
    1006941    }
    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 */
     950int 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  
    2525
    2626
    27 /** Pointer to the core (/common) state of a VirtIO PCI device. */
     27/** Pointer to the core shared state of a VirtIO PCI device */
    2828typedef struct VPCISTATE *PVPCISTATE;
     29/** Pointer to the core ring-3 state of a VirtIO PCI device */
     30typedef struct VPCISTATER3 *PVPCISTATER3;
     31/** Pointer to the core ring-0 state of a VirtIO PCI device */
     32typedef struct VPCISTATER0 *PVPCISTATER0;
     33/** Pointer to the core raw-mode state of a VirtIO PCI device */
     34typedef struct VPCISTATERC *PVPCISTATERC;
     35
     36/** Pointer to the core current context state of a VirtIO PCI device */
     37typedef CTX_SUFF(PVPCISTATE) PVPCISTATECC;
     38/** The core current context state of a VirtIO PCI device */
     39typedef struct CTX_SUFF(VPCISTATE) VPCISTATECC;
    2940
    3041
     
    121132typedef VRING *PVRING;
    122133
     134typedef struct VQUEUE
     135{
     136    VRING       VRing;
     137    uint16_t    uNextAvailIndex;
     138    uint16_t    uNextUsedIndex;
     139    uint32_t    uPageNumber;
     140    char        szName[16];
     141} VQUEUE;
     142typedef VQUEUE *PVQUEUE;
     143
    123144/**
    124145 * Queue callback (consumer?).
    125146 *
    126147 * @param   pDevIns         The device instance.
    127  * @param   pVPciState      Pointer to the VirtIO PCI core state.
    128148 * @param   pQueue          Pointer to the queue structure.
    129149 */
    130 typedef DECLCALLBACK(void) FNVPCIQUEUECALLBACK(PPDMDEVINS pDevIns, PVPCISTATE pVPciState, struct VQueue *pQueue);
     150typedef DECLCALLBACK(void) FNVPCIQUEUECALLBACK(PPDMDEVINS pDevIns, PVQUEUE pQueue);
    131151/** Pointer to a VQUEUE callback function. */
    132152typedef FNVPCIQUEUECALLBACK *PFNVPCIQUEUECALLBACK;
    133153
    134 typedef struct VQueue
    135 {
    136     VRING    VRing;
    137     uint16_t uNextAvailIndex;
    138     uint16_t uNextUsedIndex;
    139     uint32_t uPageNumber;
     154typedef struct VQUEUER3
     155{
    140156    R3PTRTYPE(PFNVPCIQUEUECALLBACK) pfnCallback;
    141     R3PTRTYPE(const char *)         pcszName;
    142 } VQUEUE;
    143 typedef VQUEUE *PVQUEUE;
     157} VQUEUER3;
     158typedef VQUEUER3 *PVQUEUER3;
    144159
    145160typedef struct VQueueElemSeg
     
    170185
    171186/**
    172  * The core (/common) state of the VirtIO PCI device
     187 * The core shared state of a VirtIO PCI device
     188 */
     189typedef 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
    173228 *
    174229 * @implements  PDMILEDPORTS
    175230 */
    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 
     231typedef struct VPCISTATER3
     232{
    186233    /** Status LUN: Base interface. */
    187     PDMIBASE               IBase;
     234    PDMIBASE                        IBase;
    188235    /** Status LUN: LED port interface. */
    189     PDMILEDPORTS           ILeds;
     236    PDMILEDPORTS                    ILeds;
    190237    /** 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 */
     249typedef struct VPCISTATER0
     250{
     251    uint64_t                uUnused;
     252} VPCISTATER0;
     253
     254
     255/**
     256 * The core raw-mode state of a VirtIO PCI device
     257 */
     258typedef struct VPCISTATERC
     259{
     260    uint64_t                uUnused;
     261} VPCISTATERC;
     262
    234263
    235264/** @name VirtIO port I/O callbacks.
     
    242271     DECLCALLBACKMEMBER(int,      pfnGetConfig)(PVPCISTATE pVPciState, uint32_t offCfg, uint32_t cb, void *pvData);
    243272     DECLCALLBACKMEMBER(int,      pfnSetConfig)(PVPCISTATE pVPciState, uint32_t offCfg, uint32_t cb, void *pvData);
    244      DECLCALLBACKMEMBER(int,      pfnReset)(PVPCISTATE pVPciState);
    245      DECLCALLBACKMEMBER(void,     pfnReady)(PVPCISTATE pVPciState);
     273     DECLCALLBACKMEMBER(int,      pfnReset)(PPDMDEVINS pDevIns);
     274     DECLCALLBACKMEMBER(void,     pfnReady)(PPDMDEVINS pDevIns);
    246275} VPCIIOCALLBACKS;
    247276/** Pointer to a const VirtIO port I/O callback structure. */
     
    249278/** @} */
    250279
    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);
     280int   vpciR3Init(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVPCISTATECC pThisCC, uint16_t uDeviceId, uint16_t uClass, uint32_t cQueues);
     281int   vpciRZInit(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVPCISTATECC pThisCC);
     282int   vpciR3Term(PPDMDEVINS pDevIns, PVPCISTATE pThis);
     283
     284int   vpciRaiseInterrupt(PPDMDEVINS pDevIns, PVPCISTATE pThis, int rcBusy, uint8_t u8IntCause);
     285int   vpciIOPortIn(PPDMDEVINS pDevIns, PVPCISTATE pThis, RTIOPORT offPort,
     286                   uint32_t *pu32, unsigned cb,PCVPCIIOCALLBACKS pCallbacks);
     287int   vpciIOPortOut(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVPCISTATECC pThisCC, RTIOPORT offPort,
     288                    uint32_t u32, unsigned cb, PCVPCIIOCALLBACKS pCallbacks);
     289
     290void  vpciR3SetWriteLed(PVPCISTATE pThis, bool fOn);
     291void  vpciR3SetReadLed(PVPCISTATE pThis, bool fOn);
     292int   vpciR3SaveExec(PCPDMDEVHLPR3 pHlp, PVPCISTATE pThis, PSSMHANDLE pSSM);
     293int   vpciR3LoadExec(PCPDMDEVHLPR3 pHlp, PVPCISTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t cQueues);
     294void  vpciReset(PPDMDEVINS pDevIns, PVPCISTATE pThis);
     295void *vpciR3QueryInterface(PVPCISTATECC pThisCC, const char *pszIID);
     296PVQUEUE vpciR3AddQueue(PVPCISTATE pThis, PVPCISTATECC pThisCC, unsigned uSize, PFNVPCIQUEUECALLBACK pfnCallback, const char *pcszName);
    277297
    278298#define VPCI_CS
    279 DECLINLINE(int) vpciCsEnter(VPCISTATE *pState, int rcBusy)
     299DECLINLINE(int) vpciCsEnter(PPDMDEVINS pDevIns, PVPCISTATE pThis, int rcBusy)
    280300{
    281301#ifdef VPCI_CS
    282     STAM_PROFILE_START(&pState->CTX_SUFF(StatCs), a);
    283     int rc = PDMCritSectEnter(&pState->cs, rcBusy);
    284     STAM_PROFILE_STOP(&pState->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);
    285305    return rc;
    286306#else
     307    RT_NOREF(pDevIns, pThis, rcBusy);
    287308    return VINF_SUCCESS;
    288309#endif
    289310}
    290311
    291 DECLINLINE(void) vpciCsLeave(VPCISTATE *pState)
     312DECLINLINE(void) vpciCsLeave(PPDMDEVINS pDevIns, PVPCISTATE pThis)
    292313{
    293314#ifdef VPCI_CS
    294     PDMCritSectLeave(&pState->cs);
     315    PDMDevHlpCritSectLeave(pDevIns, &pThis->cs);
    295316#endif
    296317}
    297318
    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);
     319void vringSetNotification(PPDMDEVINS pDevIns, PVRING pVRing, bool fEnabled);
     320
     321DECLINLINE(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
     328bool vqueueSkip(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue);
     329bool vqueueGet(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true);
     330void vqueuePut(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t uLen, uint32_t uReserved = 0);
     331void vqueueNotify(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue);
     332void vqueueSync(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue);
     333
     334DECLINLINE(bool) vqueuePeek(PPDMDEVINS pDevIns, PVPCISTATE pThis, PVQUEUE pQueue, PVQUEUEELEM pElem)
     335{
     336    return vqueueGet(pDevIns, pThis, pQueue, pElem, /* fRemove */ false);
     337}
     338
     339DECLINLINE(bool) vqueueIsReady(PVQUEUE pQueue)
     340{
    324341    return !!pQueue->VRing.addrAvail;
    325342}
    326343
    327 DECLINLINE(bool) vqueueIsEmpty(PVPCISTATE pState, PVQUEUE pQueue)
    328 {
    329     return (vringReadAvailIndex(pState, &pQueue->VRing) == pQueue->uNextAvailIndex);
    330 }
     344DECLINLINE(bool) vqueueIsEmpty(PPDMDEVINS pDevIns, PVQUEUE pQueue)
     345{
     346    return vringReadAvailIndex(pDevIns, &pQueue->VRing) == pQueue->uNextAvailIndex;
     347}
     348
     349void vpcR3iDumpStateWorker(PVPCISTATE pThis, PCDBGFINFOHLP pHlp);
    331350
    332351#endif /* !VBOX_INCLUDED_SRC_VirtIO_Virtio_h */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette