VirtualBox

Ignore:
Timestamp:
Nov 17, 2018 1:26:43 AM (6 years ago)
Author:
vboxsync
Message:

VMMDev/HGCM: Use an allocation cache for HGCM command structures with 6 or fewer parameters (also connect and disconnect). Moved the connection location out of the union just like the parameters, as it's 132 bytes big. bugref:9172

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp

    r75532 r75537  
    133133    bool                fRestored;
    134134
     135    /** Set if allocated from the memory cache, clear if heap. */
     136    bool                fMemCache;
     137
    135138    /** GC physical address of the guest request. */
    136139    RTGCPHYS            GCPhys;
     
    157160        {
    158161            uint32_t            u32ClientID;
    159             HGCMServiceLocation loc;
     162            HGCMServiceLocation *pLoc;  /**< Allocated after this structure. */
    160163        } connect;
    161164
     
    191194
    192195
     196/**
     197 * Version for the memory cache.
     198 */
     199typedef struct VBOXHGCMCMDCACHED
     200{
     201    VBOXHGCMCMD         Core;           /**< 112 */
     202    VBOXHGCMGUESTPARM   aGuestParms[6]; /**< 40 * 6 = 240 */
     203    VBOXHGCMSVCPARM     aHostParms[6];  /**< 24 * 6 = 144 */
     204} VBOXHGCMCMDCACHED;                    /**< 112+240+144 = 496 */
     205AssertCompile(sizeof(VBOXHGCMCMD) <= 112);
     206AssertCompile(sizeof(VBOXHGCMGUESTPARM) <= 40);
     207AssertCompile(sizeof(VBOXHGCMSVCPARM) <= 24);
     208AssertCompile(sizeof(VBOXHGCMCMDCACHED) <= 512);
     209AssertCompile(sizeof(VBOXHGCMCMDCACHED) > sizeof(VBOXHGCMCMD) + sizeof(HGCMServiceLocation));
     210
     211
    193212static int vmmdevHGCMCmdListLock(PVMMDEV pThis)
    194213{
     
    212231 * @param   cParms          Number of HGCM parameters for VBOXHGCMCMDTYPE_CALL command.
    213232 */
    214 static PVBOXHGCMCMD vmmdevHGCMCmdAlloc(VBOXHGCMCMDTYPE enmCmdType, RTGCPHYS GCPhys, uint32_t cbRequest, uint32_t cParms)
    215 {
     233static PVBOXHGCMCMD vmmdevHGCMCmdAlloc(PVMMDEV pThis, VBOXHGCMCMDTYPE enmCmdType, RTGCPHYS GCPhys, uint32_t cbRequest, uint32_t cParms)
     234{
     235#if 1
     236    /*
     237     * Try use the cache.
     238     */
     239    VBOXHGCMCMDCACHED *pCmdCached;
     240    AssertCompile(sizeof(*pCmdCached) >= sizeof(VBOXHGCMCMD) + sizeof(HGCMServiceLocation));
     241    if (cParms <= RT_ELEMENTS(pCmdCached->aGuestParms))
     242    {
     243        int rc = RTMemCacheAllocEx(pThis->hHgcmCmdCache, (void **)&pCmdCached);
     244        if (RT_SUCCESS(rc))
     245        {
     246            RT_ZERO(*pCmdCached);
     247            pCmdCached->Core.fMemCache  = true;
     248            pCmdCached->Core.GCPhys     = GCPhys;
     249            pCmdCached->Core.cbRequest  = cbRequest;
     250            pCmdCached->Core.enmCmdType = enmCmdType;
     251            if (enmCmdType == VBOXHGCMCMDTYPE_CALL)
     252            {
     253                pCmdCached->Core.u.call.cParms       = cParms;
     254                pCmdCached->Core.u.call.paGuestParms = pCmdCached->aGuestParms;
     255                pCmdCached->Core.u.call.paHostParms  = pCmdCached->aHostParms;
     256            }
     257            else if (enmCmdType == VBOXHGCMCMDTYPE_CONNECT)
     258                pCmdCached->Core.u.connect.pLoc = (HGCMServiceLocation *)(&pCmdCached->Core + 1);
     259
     260            return &pCmdCached->Core;
     261        }
     262        return NULL;
     263    }
     264    STAM_REL_COUNTER_INC(&pThis->StatHgcmLargeCmdAllocs);
     265
     266#else
     267    RT_NOREF(pThis);
     268#endif
     269
    216270    /* Size of required memory buffer. */
    217     const uint32_t cbCmd =   sizeof(struct VBOXHGCMCMD)
    218                            + cParms * sizeof(VBOXHGCMGUESTPARM)
    219                            + cParms * sizeof(VBOXHGCMSVCPARM);
     271    const uint32_t cbCmd = sizeof(VBOXHGCMCMD) + cParms * (sizeof(VBOXHGCMGUESTPARM) + sizeof(VBOXHGCMSVCPARM))
     272                         + (enmCmdType == VBOXHGCMCMDTYPE_CONNECT ? sizeof(HGCMServiceLocation) : 0);
    220273
    221274    PVBOXHGCMCMD pCmd = (PVBOXHGCMCMD)RTMemAllocZ(cbCmd);
     
    237290            }
    238291        }
     292        else if (enmCmdType == VBOXHGCMCMDTYPE_CONNECT)
     293            pCmd->u.connect.pLoc = (HGCMServiceLocation *)(pCmd + 1);
    239294    }
    240295    return pCmd;
     
    276331        }
    277332
    278         RTMemFree(pCmd);
     333#if 1
     334        if (pCmd->fMemCache)
     335            RTMemCacheFree(pThis->hHgcmCmdCache, pCmd);
     336        else
     337#endif
     338            RTMemFree(pCmd);
    279339    }
    280340}
     
    358418    pCmd->enmRequestType        = pHGCMConnect->header.header.requestType;
    359419    pCmd->u.connect.u32ClientID = pHGCMConnect->u32ClientID;
    360     pCmd->u.connect.loc         = pHGCMConnect->loc;
     420    *pCmd->u.connect.pLoc       = pHGCMConnect->loc;
    361421}
    362422
     
    371431    int rc = VINF_SUCCESS;
    372432
    373     PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(VBOXHGCMCMDTYPE_CONNECT, GCPhys, pHGCMConnect->header.header.size, 0);
     433    PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(pThis, VBOXHGCMCMDTYPE_CONNECT, GCPhys, pHGCMConnect->header.header.size, 0);
    374434    if (pCmd)
    375435    {
     
    377437
    378438        /* Only allow the guest to use existing services! */
    379         ASSERT_GUEST(pCmd->u.connect.loc.type == VMMDevHGCMLoc_LocalHost_Existing);
    380         pCmd->u.connect.loc.type = VMMDevHGCMLoc_LocalHost_Existing;
     439        ASSERT_GUEST(pHGCMConnect->loc.type == VMMDevHGCMLoc_LocalHost_Existing);
     440        pCmd->u.connect.pLoc->type = VMMDevHGCMLoc_LocalHost_Existing;
    381441
    382442        vmmdevHGCMAddCommand(pThis, pCmd);
    383         rc = pThis->pHGCMDrv->pfnConnect(pThis->pHGCMDrv, pCmd, &pCmd->u.connect.loc, &pCmd->u.connect.u32ClientID);
     443        rc = pThis->pHGCMDrv->pfnConnect(pThis->pHGCMDrv, pCmd, pCmd->u.connect.pLoc, &pCmd->u.connect.u32ClientID);
    384444        if (RT_FAILURE(rc))
    385445            vmmdevHGCMRemoveCommand(pThis, pCmd);
     
    414474    int rc = VINF_SUCCESS;
    415475
    416     PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(VBOXHGCMCMDTYPE_DISCONNECT, GCPhys, pHGCMDisconnect->header.header.size, 0);
     476    PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(pThis, VBOXHGCMCMDTYPE_DISCONNECT, GCPhys, pHGCMDisconnect->header.header.size, 0);
    417477    if (pCmd)
    418478    {
     
    640700 * @param   pcbHGCMParmStruct Where to store size of used HGCM parameter structure.
    641701 */
    642 static int vmmdevHGCMCallAlloc(const VMMDevHGCMCall *pHGCMCall, uint32_t cbHGCMCall, RTGCPHYS GCPhys,
     702static int vmmdevHGCMCallAlloc(PVMMDEV pThis, const VMMDevHGCMCall *pHGCMCall, uint32_t cbHGCMCall, RTGCPHYS GCPhys,
    643703                               VMMDevRequestType enmRequestType, PVBOXHGCMCMD *ppCmd, uint32_t *pcbHGCMParmStruct)
    644704{
     
    660720    RT_UNTRUSTED_VALIDATED_FENCE();
    661721
    662     PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(VBOXHGCMCMDTYPE_CALL, GCPhys, cbHGCMCall, cParms);
     722    PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(pThis, VBOXHGCMCMDTYPE_CALL, GCPhys, cbHGCMCall, cParms);
    663723    if (pCmd == NULL)
    664724        return VERR_NO_MEMORY;
     
    919979    PVBOXHGCMCMD pCmd;
    920980    uint32_t cbHGCMParmStruct;
    921     int rc = vmmdevHGCMCallAlloc(pHGCMCall, cbHGCMCall, GCPhys, enmRequestType, &pCmd, &cbHGCMParmStruct);
     981    int rc = vmmdevHGCMCallAlloc(pThis, pHGCMCall, cbHGCMCall, GCPhys, enmRequestType, &pCmd, &cbHGCMParmStruct);
    922982    if (RT_SUCCESS(rc))
    923983    {
     
    14491509            {
    14501510                SSMR3PutU32(pSSM, pCmd->u.connect.u32ClientID);
    1451                 SSMR3PutMem(pSSM, &pCmd->u.connect.loc, sizeof(pCmd->u.connect.loc));
     1511                SSMR3PutMem(pSSM, pCmd->u.connect.pLoc, sizeof(*pCmd->u.connect.pLoc));
    14521512            }
    14531513            else if (pCmd->enmCmdType == VBOXHGCMCMDTYPE_DISCONNECT)
     
    15241584            AssertRCReturn(rc, rc);
    15251585
    1526             PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(enmCmdType, GCPhys, cbRequest, cParms);
     1586            PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(pThis, enmCmdType, GCPhys, cbRequest, cParms);
    15271587            AssertReturn(pCmd, VERR_NO_MEMORY);
    15281588
     
    15891649            {
    15901650                SSMR3GetU32(pSSM, &pCmd->u.connect.u32ClientID);
    1591                 rc = SSMR3GetMem(pSSM, &pCmd->u.connect.loc, sizeof(pCmd->u.connect.loc));
     1651                rc = SSMR3GetMem(pSSM, pCmd->u.connect.pLoc, sizeof(*pCmd->u.connect.pLoc));
    15921652                AssertRCReturn(rc, rc);
    15931653            }
     
    16461706            AssertRCReturn(rc, rc);
    16471707
    1648             PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(enmCmdType, GCPhys, cbRequest, cLinAddrs);
     1708            PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(pThis, enmCmdType, GCPhys, cbRequest, cLinAddrs);
    16491709            AssertReturn(pCmd, VERR_NO_MEMORY);
    16501710
     
    17041764            LogFlowFunc(("Restoring %RGp size %x bytes\n", GCPhys, cbRequest));
    17051765
    1706             PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(VBOXHGCMCMDTYPE_LOADSTATE, GCPhys, cbRequest, 0);
     1766            PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(pThis, VBOXHGCMCMDTYPE_LOADSTATE, GCPhys, cbRequest, 0);
    17071767            AssertReturn(pCmd, VERR_NO_MEMORY);
    17081768
     
    17401800    }
    17411801
    1742     PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(VBOXHGCMCMDTYPE_CONNECT, pLoadedCmd->GCPhys, cbReq, 0);
     1802    PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(pThis, VBOXHGCMCMDTYPE_CONNECT, pLoadedCmd->GCPhys, cbReq, 0);
    17431803    AssertReturn(pCmd, VERR_NO_MEMORY);
    17441804
     
    17841844    }
    17851845
    1786     PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(VBOXHGCMCMDTYPE_DISCONNECT, pLoadedCmd->GCPhys, cbReq, 0);
     1846    PVBOXHGCMCMD pCmd = vmmdevHGCMCmdAlloc(pThis, VBOXHGCMCMDTYPE_DISCONNECT, pLoadedCmd->GCPhys, cbReq, 0);
    17871847    AssertReturn(pCmd, VERR_NO_MEMORY);
    17881848
     
    18281888    PVBOXHGCMCMD pCmd;
    18291889    uint32_t cbHGCMParmStruct;
    1830     rc = vmmdevHGCMCallAlloc(pReq, cbReq, pLoadedCmd->GCPhys, enmRequestType, &pCmd, &cbHGCMParmStruct);
     1890    rc = vmmdevHGCMCallAlloc(pThis, pReq, cbReq, pLoadedCmd->GCPhys, enmRequestType, &pCmd, &cbHGCMParmStruct);
    18311891    if (RT_FAILURE(rc))
    18321892        return rc;
     
    20142074                    {
    20152075                        vmmdevHGCMAddCommand(pThis, pCmd);
    2016                         rcCmd = pThis->pHGCMDrv->pfnConnect(pThis->pHGCMDrv, pCmd, &pCmd->u.connect.loc, &pCmd->u.connect.u32ClientID);
     2076                        rcCmd = pThis->pHGCMDrv->pfnConnect(pThis->pHGCMDrv, pCmd, pCmd->u.connect.pLoc,
     2077                                                            &pCmd->u.connect.u32ClientID);
    20172078                        if (RT_FAILURE(rcCmd))
    20182079                            vmmdevHGCMRemoveCommand(pThis, pCmd);
     
    20922153}
    20932154
    2094 /** Deallocate HGCM commands.
     2155
     2156/**
     2157 * Counterpart to vmmdevHGCMInit().
    20952158 *
    20962159 * @param   pThis           The VMMDev instance data.
     
    20992162{
    21002163    LogFlowFunc(("\n"));
     2164
     2165    RTCritSectDelete(&pThis->critsectHGCMCmdList);
    21012166
    21022167    PVBOXHGCMCMD pCmd, pNext;
     
    21062171        vmmdevHGCMCmdFree(pThis, pCmd);
    21072172    }
    2108 }
     2173
     2174    AssertCompile((uintptr_t)NIL_RTMEMCACHE == 0);
     2175    if (pThis->hHgcmCmdCache != NIL_RTMEMCACHE)
     2176    {
     2177        RTMemCacheDestroy(pThis->hHgcmCmdCache);
     2178        pThis->hHgcmCmdCache = NIL_RTMEMCACHE;
     2179    }
     2180}
     2181
     2182
     2183/**
     2184 * Initializes the HGCM specific state.
     2185 *
     2186 * Keeps VBOXHGCMCMDCACHED and friends local.
     2187 *
     2188 * @returns VBox status code.
     2189 * @param   pThis           The VMMDev instance data.
     2190 */
     2191int vmmdevHGCMInit(PVMMDEV pThis)
     2192{
     2193    RTListInit(&pThis->listHGCMCmd);
     2194
     2195    int rc = RTCritSectInit(&pThis->critsectHGCMCmdList);
     2196    AssertLogRelRCReturn(rc, rc);
     2197
     2198    rc = RTMemCacheCreate(&pThis->hHgcmCmdCache, sizeof(VBOXHGCMCMDCACHED), 64, _1M, NULL, NULL, NULL, 0);
     2199    AssertLogRelRCReturn(rc, rc);
     2200
     2201    pThis->u32HGCMEnabled = 0;
     2202
     2203    return VINF_SUCCESS;
     2204}
     2205
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