VirtualBox

Changeset 7671 in vbox


Ignore:
Timestamp:
Apr 1, 2008 7:56:35 AM (17 years ago)
Author:
vboxsync
Message:

PCNet: Create private PCI memory for shared RX/TX descriptors and buffers.

File:
1 edited

Legend:

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

    r7641 r7671  
    5353#include <VBox/pgm.h>
    5454#include <VBox/vm.h> /* for VM_IS_EMT */
     55#include <VBox/DevPCNet.h>
    5556#include <iprt/asm.h>
    5657#include <iprt/assert.h>
     
    229230#endif
    230231
     232    /** The host context of the shared memory used for the private interface. */
     233    PPCNETGUESTSHAREDMEMORY             pSharedMMIOHC;
     234    /** The hypervisor/guest context of the shared memory used for the private interface. */
     235    GCPTRTYPE(PPCNETGUESTSHAREDMEMORY)  pSharedMMIOGC;
     236
     237    /** True if host and guest admitted to use the private interface. */
     238    bool                                fPrivIfEnabled;
    231239    bool                                fGCEnabled;
    232240    bool                                fR0Enabled;
    233241    bool                                fAm79C973;
    234     bool                                afAlignment[1];
    235242    uint32_t                            u32LinkSpeed;
    236243
     
    594601    uint8_t    ownbyte;
    595602
    596     if (RT_UNLIKELY(BCR_SWSTYLE(pData) == 0))
     603    if (pData->fPrivIfEnabled)
     604    {
     605        /* RX/TX descriptors shared between host and guest => direct copy */
     606        uint8_t *pv = (uint8_t*)pData->CTXSUFF(pSharedMMIO)
     607                    + (addr - pData->GCTDRA)
     608                    + pData->CTXSUFF(pSharedMMIO)->V.V1.u32OffTxDescriptors;
     609        if (!(pv[7] & 0x80) && fRetIfNotOwn)
     610            return false;
     611        memcpy(tmd, pv, 16);
     612        return true;
     613    }
     614    else if (RT_UNLIKELY(BCR_SWSTYLE(pData) == 0))
    597615    {
    598616        uint16_t xda[4];
     
    645663    STAM_PROFILE_ADV_START(&pData->CTXSUFF(StatTmdStore), a);
    646664    PPDMDEVINS pDevIns = PCNETSTATE_2_DEVINS(pData);
    647     if (RT_UNLIKELY(BCR_SWSTYLE(pData) == 0))
     665    if (pData->fPrivIfEnabled)
     666    {
     667        /* RX/TX descriptors shared between host and guest => direct copy */
     668        uint8_t *pv = (uint8_t*)pData->CTXSUFF(pSharedMMIO)
     669                    + (addr - pData->GCTDRA)
     670                    + pData->CTXSUFF(pSharedMMIO)->V.V1.u32OffTxDescriptors;
     671        memcpy(pv, tmd, 16);
     672        pv[7] &= ~0x80;
     673    }
     674    else if (RT_UNLIKELY(BCR_SWSTYLE(pData) == 0))
    648675    {
    649676        uint16_t xda[4];
     
    693720    uint8_t    ownbyte;
    694721
    695     if (RT_UNLIKELY(BCR_SWSTYLE(pData) == 0))
     722    if (pData->fPrivIfEnabled)
     723    {
     724        /* RX/TX descriptors shared between host and guest => direct copy */
     725        uint8_t *pv = (uint8_t*)pData->CTXSUFF(pSharedMMIO)
     726                    + (addr - pData->GCRDRA)
     727                    + pData->CTXSUFF(pSharedMMIO)->V.V1.u32OffRxDescriptors;
     728        if (!(pv[7] & 0x80) && fRetIfNotOwn)
     729            return false;
     730        memcpy(rmd, pv, 16);
     731        return true;
     732    }
     733    else if (RT_UNLIKELY(BCR_SWSTYLE(pData) == 0))
    696734    {
    697735        uint16_t rda[4];
     
    742780{
    743781    PPDMDEVINS pDevIns = PCNETSTATE_2_DEVINS(pData);
    744     if (RT_UNLIKELY(BCR_SWSTYLE(pData) == 0))
     782    if (pData->fPrivIfEnabled)
     783    {
     784        /* RX/TX descriptors shared between host and guest => direct copy */
     785        uint8_t *pv = (uint8_t*)pData->CTXSUFF(pSharedMMIO)
     786                    + (addr - pData->GCRDRA)
     787                    + pData->CTXSUFF(pSharedMMIO)->V.V1.u32OffRxDescriptors;
     788        memcpy(pv, rmd, 16);
     789        pv[7] &= ~0x80;
     790    }
     791    else if (RT_UNLIKELY(BCR_SWSTYLE(pData) == 0))
    745792    {
    746793        uint16_t rda[4];
     
    814861
    815862#ifdef IN_RING3
     863
     864/**
     865 * Initialize the shared memory for the private guest interface.
     866 */
     867static void pcnetInitSharedMemory(PCNetState *pData)
     868{
     869    uint32_t u32Off = 0;
     870    memset(pData->pSharedMMIOHC, 0, sizeof(PCNETGUESTSHAREDMEMORY));
     871    pData->pSharedMMIOHC->u32Size = sizeof(PCNETGUESTSHAREDMEMORY);
     872    pData->pSharedMMIOHC->u32Version = PCNET_GUEST_INTERFACE_VERSION;
     873    u32Off = 2048; /* Leave some space for more fields within the header */
     874    pData->pSharedMMIOHC->V.V1.u32OffTxDescriptors = u32Off;
     875    u32Off = RT_ALIGN(u32Off + PCNET_GUEST_TX_DESCRIPTOR_SIZE * PCNET_GUEST_MAX_TX_DESCRIPTORS, 32);
     876    pData->pSharedMMIOHC->V.V1.u32OffRxDescriptors = u32Off;
     877    u32Off = RT_ALIGN(u32Off + PCNET_GUEST_RX_DESCRIPTOR_SIZE * PCNET_GUEST_MAX_RX_DESCRIPTORS, 32);
     878    /* Map the RX/TX descriptors into the hypervisor. Make sure we don't need too much space. */
     879    AssertRelease(u32Off <= 8192);
     880    pData->pSharedMMIOHC->V.V1.u32OffTxBuffers = u32Off;
     881    u32Off = RT_ALIGN(u32Off + PCNET_GUEST_NIC_BUFFER_SIZE * PCNET_GUEST_MAX_TX_DESCRIPTORS, 32);
     882    pData->pSharedMMIOHC->V.V1.u32OffRxBuffers = u32Off;
     883    pData->pSharedMMIOHC->fFlags = PCNET_GUEST_FLAGS_ADMIT_HOST;
     884    u32Off = RT_ALIGN(u32Off + PCNET_GUEST_NIC_BUFFER_SIZE * PCNET_GUEST_MAX_RX_DESCRIPTORS, 32);
     885    AssertRelease(u32Off <= PCNET_GUEST_SHARED_MEMORY_SIZE);
     886}
    816887
    817888#define MULTICAST_FILTER_LEN 8
     
    13841455} while (0)
    13851456
     1457    bool fPrivIfEnabled =       pData->pSharedMMIOHC
     1458                          && !!(pData->pSharedMMIOHC->fFlags & PCNET_GUEST_FLAGS_ADMIT_GUEST);
     1459    if (fPrivIfEnabled != pData->fPrivIfEnabled)
     1460    {
     1461        pData->fPrivIfEnabled = fPrivIfEnabled;
     1462        LogRel(("PCNet#%d: %s private interface\n", PCNET_INST_NR, fPrivIfEnabled ? "Enabling" : "Disabling"));
     1463    }
    13861464    if (BCR_SSIZE32(pData))
    13871465    {
     
    22232301                {
    22242302                    AssertMsg(fDropFrame, ("pcnetTransmit: Frame is too big!!! %d bytes\n",
    2225                                            pData->cbSendFrame + cb));
     2303                                pData->cbSendFrame + cb));
    22262304                    fDropFrame = true;
    22272305                }
     
    22292307                {
    22302308                    Log(("#%d pcnetTransmit: stp: cb=%d xmtrc=%#x-%#x\n", PCNET_INST_NR,
    2231                          pData->cbSendFrame, iStart, CSR_XMTRC(pData)));
     2309                                pData->cbSendFrame, iStart, CSR_XMTRC(pData)));
    22322310                    if (pcnetIsLinkUp(pData) && !fDropFrame)
    22332311                    {
     
    36983776
    36993777/**
     3778 * Callback function for mapping the MMIO region.
     3779 *
     3780 * @return VBox status code.
     3781 * @param   pPciDev         Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
     3782 * @param   iRegion         The region number.
     3783 * @param   GCPhysAddress   Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
     3784 *                          I/O port, else it's a physical address.
     3785 *                          This address is *NOT* relative to pci_mem_base like earlier!
     3786 * @param   cb              Region size.
     3787 * @param   enmType         One of the PCI_ADDRESS_SPACE_* values.
     3788 */
     3789static DECLCALLBACK(int) pcnetMMIOSharedMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion,
     3790                                            RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
     3791{
     3792    if (GCPhysAddress != NIL_RTGCPHYS)
     3793        return PDMDevHlpMMIO2Map(pPciDev->pDevIns, iRegion, GCPhysAddress);
     3794
     3795    /* nothing to clean up */
     3796    return VINF_SUCCESS;
     3797}
     3798
     3799
     3800/**
    37003801 * PCNET status info callback.
    37013802 *
     
    42844385        pcnetTimerRestore(pDevIns, pData->pTimerRestore);
    42854386    }
     4387    if (pData->pSharedMMIOHC)
     4388        pcnetInitSharedMemory(pData);
    42864389
    42874390    /** @todo How to flush the queues? */
     
    42994402    pData->pXmitQueueGC  = PDMQueueGCPtr(pData->pXmitQueueHC);
    43004403    pData->pCanRxQueueGC = PDMQueueGCPtr(pData->pCanRxQueueHC);
     4404    pData->pSharedMMIOGC += offDelta;
    43014405#ifdef PCNET_NO_POLLING
    43024406    *(RTHCUINTPTR *)&pData->pfnEMInterpretInstructionGC += offDelta;
     
    43714475     * Validate configuration.
    43724476     */
    4373     if (!CFGMR3AreValuesValid(pCfgHandle, "MAC\0CableConnected\0Am79C973\0LineSpeed\0GCEnabled\0R0Enabled\0"))
     4477    if (!CFGMR3AreValuesValid(pCfgHandle, "MAC\0CableConnected\0Am79C973\0LineSpeed\0GCEnabled\0R0Enabled\0PrivIfEnabled\0"))
    43744478        return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
    43754479                                N_("Invalid configuraton for pcnet device"));
     
    44874591    if (VBOX_FAILURE(rc))
    44884592        return rc;
     4593
     4594    bool fPrivIfEnabled;
     4595    rc = CFGMR3QueryBool(pCfgHandle, "PrivIfEnabled", &fPrivIfEnabled);
     4596    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     4597        fPrivIfEnabled = true;
     4598    else if (VBOX_FAILURE(rc))
     4599        return PDMDEV_SET_ERROR(pDevIns, rc,
     4600                                N_("Configuration error: Failed to get the \"PrivIfEnabled\" value"));
     4601
     4602    if (fPrivIfEnabled)
     4603    {
     4604        /*
     4605         * Initialize shared memory between host and guest for descriptors and RX buffers. Most guests
     4606         * should not care if there is an additional PCI ressource but just in case we made this configurable.
     4607         */
     4608        rc = PDMDevHlpMMIO2Register(pDevIns, 2, PCNET_GUEST_SHARED_MEMORY_SIZE, (void**)&pData->pSharedMMIOHC, "PCNetShMem");
     4609        if (VBOX_FAILURE(rc))
     4610            return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     4611                                       N_("Failed to allocate %u bytes of memory for the PCNet device"), PCNET_GUEST_SHARED_MEMORY_SIZE);
     4612        rc = PDMDevHlpMMHyperMapMMIO2(pDevIns, 2, 0, 8192, "PCNetShMem", &pData->pSharedMMIOGC);
     4613        if (VBOX_FAILURE(rc))
     4614            return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     4615                                       N_("Failed to map 8192 bytes of memory for the PCNet device into the hyper memory"));
     4616        pcnetInitSharedMemory(pData);
     4617        rc = PDMDevHlpPCIIORegionRegister(pDevIns, 2, PCNET_GUEST_SHARED_MEMORY_SIZE,
     4618                                          PCI_ADDRESS_SPACE_MEM, pcnetMMIOSharedMap);
     4619        if (VBOX_FAILURE(rc))
     4620            return rc;
     4621    }
    44894622
    44904623#ifdef PCNET_NO_POLLING
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