VirtualBox

Changeset 90264 in vbox


Ignore:
Timestamp:
Jul 20, 2021 7:37:24 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
145803
Message:

VMMDev: Do proper heap usage accounting for HGCM requests. bugref:9379

Location:
trunk/src/VBox/Devices/VMMDev
Files:
4 edited

Legend:

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

    r87767 r90264  
    104104#include <iprt/buildconfig.h>
    105105#include <iprt/string.h>
     106#include <iprt/system.h>
    106107#include <iprt/time.h>
    107108#ifndef IN_RC
     
    44134414     * Everything HGCM.
    44144415     */
    4415     vmmdevR3HgcmDestroy(pDevIns, pThisCC);
     4416    vmmdevR3HgcmDestroy(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVMMDEV), pThisCC);
    44164417#endif
    44174418
     
    45634564                                  "TestingEnabled|"
    45644565                                  "TestingMMIO|"
    4565                                   "TestintXmlOutputFile"
     4566                                  "TestintXmlOutputFile|"
     4567                                  "HGCMHeapBudgetDefault|"
     4568                                  "HGCMHeapBudgetLegacy|"
     4569                                  "HGCMHeapBudgetVBoxGuest|"
     4570                                  "HGCMHeapBudgetOtherDrv|"
     4571                                  "HGCMHeapBudgetRoot|"
     4572                                  "HGCMHeapBudgetSystem|"
     4573                                  "HGCMHeapBudgetReserved1|"
     4574                                  "HGCMHeapBudgetUser|"
     4575                                  "HGCMHeapBudgetGuest"
    45664576                                  ,
    45674577                                  "");
     
    46424652#endif
    46434653
     4654#ifdef VBOX_WITH_HGCM
     4655    /*
     4656     * Heap budgets for HGCM requestor categories.  Take the available host
     4657     * memory as a rough hint of how much we can handle.
     4658     */
     4659    /** @todo If we reduced the number of categories here, we could alot more to
     4660     *        each... */
     4661    uint64_t cbDefaultBudget = 0;
     4662    if (RT_FAILURE(RTSystemQueryTotalRam(&cbDefaultBudget)))
     4663        cbDefaultBudget = 16 * _1G64;
     4664    LogFunc(("RTSystemQueryTotalRam -> %'RU64 (%RX64)\n", cbDefaultBudget, cbDefaultBudget));
     4665# if ARCH_BITS == 32
     4666    cbDefaultBudget  = RT_MIN(cbDefaultBudget, _512M);
     4667# endif
     4668    cbDefaultBudget /= 8;                               /* One eighth of physical memory ... */
     4669    cbDefaultBudget /= RT_ELEMENTS(pThisCC->aHgcmAcc);  /* over 8 accounting categories. (8GiB -> 64MiB) */
     4670    cbDefaultBudget  = RT_MIN(cbDefaultBudget, _512M);  /* max 512MiB */
     4671    cbDefaultBudget  = RT_MAX(cbDefaultBudget, _32M);   /* min  32MiB */
     4672    rc = pHlp->pfnCFGMQueryU64Def(pCfg, "HGCMHeapBudgetDefault", &cbDefaultBudget, cbDefaultBudget);
     4673    if (RT_FAILURE(rc))
     4674        return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed querying \"HGCMHeapBudgetDefault\" as a 64-bit unsigned integer"));
     4675
     4676    LogRel(("VMMDev: cbDefaultBudget: %'RU64 (%RX64)\n", cbDefaultBudget, cbDefaultBudget));
     4677    static const struct { const char *pszName; unsigned idx; } s_aCfgHeapBudget[] =
     4678    {
     4679        { "HGCMHeapBudgetLegacy",       VMMDEV_REQUESTOR_USR_NOT_GIVEN  },
     4680        { "HGCMHeapBudgetVBoxGuest",    VMMDEV_REQUESTOR_USR_DRV        },
     4681        { "HGCMHeapBudgetOtherDrv",     VMMDEV_REQUESTOR_USR_DRV_OTHER  },
     4682        { "HGCMHeapBudgetRoot",         VMMDEV_REQUESTOR_USR_ROOT       },
     4683        { "HGCMHeapBudgetSystem",       VMMDEV_REQUESTOR_USR_SYSTEM     },
     4684        { "HGCMHeapBudgetReserved1",    VMMDEV_REQUESTOR_USR_RESERVED1  },
     4685        { "HGCMHeapBudgetUser",         VMMDEV_REQUESTOR_USR_USER       },
     4686        { "HGCMHeapBudgetGuest",        VMMDEV_REQUESTOR_USR_GUEST      },
     4687    };
     4688    AssertCompile(RT_ELEMENTS(s_aCfgHeapBudget) == RT_ELEMENTS(pThisCC->aHgcmAcc));
     4689    for (uintptr_t i = 0; i < RT_ELEMENTS(s_aCfgHeapBudget); i++)
     4690    {
     4691        uintptr_t const idx = s_aCfgHeapBudget[i].idx;
     4692        rc = pHlp->pfnCFGMQueryU64Def(pCfg, s_aCfgHeapBudget[i].pszName,
     4693                                      &pThisCC->aHgcmAcc[idx].cbHeapBudgetConfig, cbDefaultBudget);
     4694        if (RT_FAILURE(rc))
     4695            return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     4696                                       N_("Configuration error: Failed querying \"%s\" as a 64-bit unsigned integer"),
     4697                                       s_aCfgHeapBudget[i].pszName);
     4698        pThisCC->aHgcmAcc[idx].cbHeapBudget = pThisCC->aHgcmAcc[idx].cbHeapBudgetConfig;
     4699        if (pThisCC->aHgcmAcc[idx].cbHeapBudgetConfig != cbDefaultBudget)
     4700            LogRel(("VMMDev: %s: %'RU64 (%#RX64)\n", s_aCfgHeapBudget[i].pszName,
     4701                    pThisCC->aHgcmAcc[idx].cbHeapBudgetConfig, pThisCC->aHgcmAcc[idx].cbHeapBudgetConfig));
     4702
     4703        const char * const pszCatName = &s_aCfgHeapBudget[i].pszName[sizeof("HGCMHeapBudget") - 1];
     4704        PDMDevHlpSTAMRegisterF(pDevIns, &pThisCC->aHgcmAcc[idx].cbHeapBudget, STAMTYPE_U64, STAMVISIBILITY_ALWAYS,
     4705                               STAMUNIT_BYTES, "Currently available budget", "HGCM-%s/BudgetAvailable", pszCatName);
     4706        PDMDevHlpSTAMRegisterF(pDevIns, &pThisCC->aHgcmAcc[idx].cbHeapBudgetConfig, STAMTYPE_U64, STAMVISIBILITY_ALWAYS,
     4707                               STAMUNIT_BYTES, "Configured budget",          "HGCM-%s/BudgetConfig", pszCatName);
     4708        PDMDevHlpSTAMRegisterF(pDevIns, &pThisCC->aHgcmAcc[idx].cbHeapTotal, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS,
     4709                               STAMUNIT_BYTES, "Total heap usage",           "HGCM-%s/cbHeapTotal", pszCatName);
     4710        PDMDevHlpSTAMRegisterF(pDevIns, &pThisCC->aHgcmAcc[idx].cTotalMessages, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS,
     4711                               STAMUNIT_COUNT, "Total messages",             "HGCM-%s/cTotalMessages", pszCatName);
     4712    }
     4713#endif
     4714
     4715    /*
     4716     * <missing comment>
     4717     */
    46444718    pThis->cbGuestRAM = MMR3PhysGetRamSize(PDMDevHlpGetVM(pDevIns));
    46454719
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp

    r83558 r90264  
    182182    PGMPAGEMAPLOCK      ReqMapLock;
    183183
     184    /** The accounting index (into VMMDEVR3::aHgcmAcc). */
     185    uint8_t             idxHeapAcc;
     186    uint8_t             abPadding[3];
     187    /** The heap cost of this command. */
     188    uint32_t            cbHeapCost;
     189
    184190    /** The STAM_GET_TS() value when the request arrived. */
    185191    uint64_t            tsArrival;
     
    231237typedef struct VBOXHGCMCMDCACHED
    232238{
    233     VBOXHGCMCMD         Core;           /**< 112 */
     239    VBOXHGCMCMD         Core;           /**< 120 */
    234240    VBOXHGCMGUESTPARM   aGuestParms[6]; /**< 40 * 6 = 240 */
    235241    VBOXHGCMSVCPARM     aHostParms[6];  /**< 24 * 6 = 144 */
    236 } VBOXHGCMCMDCACHED;                    /**< 112+240+144 = 496 */
    237 AssertCompile(sizeof(VBOXHGCMCMD) <= 112);
     242} VBOXHGCMCMDCACHED;                    /**< 120+240+144 = 504 */
     243AssertCompile(sizeof(VBOXHGCMCMD) <= 120);
    238244AssertCompile(sizeof(VBOXHGCMGUESTPARM) <= 40);
    239245AssertCompile(sizeof(VBOXHGCMSVCPARM) <= 24);
    240246AssertCompile(sizeof(VBOXHGCMCMDCACHED) <= 512);
    241247AssertCompile(sizeof(VBOXHGCMCMDCACHED) > sizeof(VBOXHGCMCMD) + sizeof(HGCMServiceLocation));
     248
     249
     250/*********************************************************************************************************************************
     251*   Internal Functions                                                                                                           *
     252*********************************************************************************************************************************/
     253DECLINLINE(void *) vmmdevR3HgcmCallMemAllocZ(PVMMDEVCC pThisCC, PVBOXHGCMCMD pCmd, size_t cbRequested);
     254
    242255
    243256
     
    268281                                         uint32_t cbRequest, uint32_t cParms, uint32_t fRequestor)
    269282{
     283    /* For heap accounting. */
     284    uintptr_t const idxHeapAcc = fRequestor != VMMDEV_REQUESTOR_LEGACY
     285                               ? fRequestor & VMMDEV_REQUESTOR_USR_MASK
     286                               : VMMDEV_REQUESTOR_USR_NOT_GIVEN;
    270287#if 1
    271288    /*
     
    276293    if (cParms <= RT_ELEMENTS(pCmdCached->aGuestParms))
    277294    {
    278         int rc = RTMemCacheAllocEx(pThisCC->hHgcmCmdCache, (void **)&pCmdCached);
    279         if (RT_SUCCESS(rc))
    280         {
    281             RT_ZERO(*pCmdCached);
    282             pCmdCached->Core.fMemCache  = true;
    283             pCmdCached->Core.GCPhys     = GCPhys;
    284             pCmdCached->Core.cbRequest  = cbRequest;
    285             pCmdCached->Core.enmCmdType = enmCmdType;
    286             pCmdCached->Core.fRequestor = fRequestor;
    287             if (enmCmdType == VBOXHGCMCMDTYPE_CALL)
    288             {
    289                 pCmdCached->Core.u.call.cParms       = cParms;
    290                 pCmdCached->Core.u.call.paGuestParms = pCmdCached->aGuestParms;
    291                 pCmdCached->Core.u.call.paHostParms  = pCmdCached->aHostParms;
    292             }
    293             else if (enmCmdType == VBOXHGCMCMDTYPE_CONNECT)
    294                 pCmdCached->Core.u.connect.pLoc = (HGCMServiceLocation *)(&pCmdCached->Core + 1);
    295 
    296             return &pCmdCached->Core;
     295        if (sizeof(*pCmdCached) <= pThisCC->aHgcmAcc[idxHeapAcc].cbHeapBudget)
     296        {
     297            int rc = RTMemCacheAllocEx(pThisCC->hHgcmCmdCache, (void **)&pCmdCached);
     298            if (RT_SUCCESS(rc))
     299            {
     300                RT_ZERO(*pCmdCached);
     301                pCmdCached->Core.fMemCache  = true;
     302                pCmdCached->Core.GCPhys     = GCPhys;
     303                pCmdCached->Core.cbRequest  = cbRequest;
     304                pCmdCached->Core.enmCmdType = enmCmdType;
     305                pCmdCached->Core.fRequestor = fRequestor;
     306                pCmdCached->Core.idxHeapAcc = (uint8_t)idxHeapAcc;
     307                pCmdCached->Core.cbHeapCost = sizeof(*pCmdCached);
     308                Log5Func(("aHgcmAcc[%zu] %#RX64 -= %#zx (%p)\n",
     309                          idxHeapAcc, pThisCC->aHgcmAcc[idxHeapAcc].cbHeapBudget, sizeof(*pCmdCached), &pCmdCached->Core));
     310                pThisCC->aHgcmAcc[idxHeapAcc].cbHeapBudget -= sizeof(*pCmdCached);
     311
     312                if (enmCmdType == VBOXHGCMCMDTYPE_CALL)
     313                {
     314                    pCmdCached->Core.u.call.cParms       = cParms;
     315                    pCmdCached->Core.u.call.paGuestParms = pCmdCached->aGuestParms;
     316                    pCmdCached->Core.u.call.paHostParms  = pCmdCached->aHostParms;
     317                }
     318                else if (enmCmdType == VBOXHGCMCMDTYPE_CONNECT)
     319                    pCmdCached->Core.u.connect.pLoc = (HGCMServiceLocation *)(&pCmdCached->Core + 1);
     320
     321                Assert(!pCmdCached->Core.pvReqLocked);
     322
     323                Log3Func(("returns %p (enmCmdType=%d GCPhys=%RGp)\n", &pCmdCached->Core, enmCmdType, GCPhys));
     324                return &pCmdCached->Core;
     325            }
    297326        }
     327        else
     328            LogFunc(("Heap budget overrun: sizeof(*pCmdCached)=%#zx aHgcmAcc[%zu].cbHeapBudget=%#RX64 - enmCmdType=%d\n",
     329                     sizeof(*pCmdCached), idxHeapAcc, pThisCC->aHgcmAcc[idxHeapAcc].cbHeapBudget, enmCmdType));
    298330        return NULL;
    299331    }
     
    307339    const uint32_t cbCmd = sizeof(VBOXHGCMCMD) + cParms * (sizeof(VBOXHGCMGUESTPARM) + sizeof(VBOXHGCMSVCPARM))
    308340                         + (enmCmdType == VBOXHGCMCMDTYPE_CONNECT ? sizeof(HGCMServiceLocation) : 0);
    309 
    310     PVBOXHGCMCMD pCmd = (PVBOXHGCMCMD)RTMemAllocZ(cbCmd);
    311     if (pCmd)
    312     {
    313         pCmd->enmCmdType = enmCmdType;
    314         pCmd->GCPhys     = GCPhys;
    315         pCmd->cbRequest  = cbRequest;
    316         pCmd->fRequestor = fRequestor;
    317 
    318         if (enmCmdType == VBOXHGCMCMDTYPE_CALL)
    319         {
    320             pCmd->u.call.cParms = cParms;
    321             if (cParms)
    322             {
    323                 pCmd->u.call.paGuestParms = (VBOXHGCMGUESTPARM *)((uint8_t *)pCmd
    324                                                                   + sizeof(struct VBOXHGCMCMD));
    325                 pCmd->u.call.paHostParms = (VBOXHGCMSVCPARM *)((uint8_t *)pCmd->u.call.paGuestParms
    326                                                                + cParms * sizeof(VBOXHGCMGUESTPARM));
    327             }
     341    if (cbCmd <= pThisCC->aHgcmAcc[idxHeapAcc].cbHeapBudget)
     342    {
     343        PVBOXHGCMCMD pCmd = (PVBOXHGCMCMD)RTMemAllocZ(cbCmd);
     344        if (pCmd)
     345        {
     346            pCmd->enmCmdType = enmCmdType;
     347            pCmd->GCPhys     = GCPhys;
     348            pCmd->cbRequest  = cbRequest;
     349            pCmd->fRequestor = fRequestor;
     350            pCmd->idxHeapAcc = (uint8_t)idxHeapAcc;
     351            pCmd->cbHeapCost = cbCmd;
     352            Log5Func(("aHgcmAcc[%zu] %#RX64 -= %#x (%p)\n", idxHeapAcc, pThisCC->aHgcmAcc[idxHeapAcc].cbHeapBudget, cbCmd, pCmd));
     353            pThisCC->aHgcmAcc[idxHeapAcc].cbHeapBudget -= cbCmd;
     354
     355            if (enmCmdType == VBOXHGCMCMDTYPE_CALL)
     356            {
     357                pCmd->u.call.cParms = cParms;
     358                if (cParms)
     359                {
     360                    pCmd->u.call.paGuestParms = (VBOXHGCMGUESTPARM *)((uint8_t *)pCmd
     361                                                                      + sizeof(struct VBOXHGCMCMD));
     362                    pCmd->u.call.paHostParms = (VBOXHGCMSVCPARM *)((uint8_t *)pCmd->u.call.paGuestParms
     363                                                                   + cParms * sizeof(VBOXHGCMGUESTPARM));
     364                }
     365            }
     366            else if (enmCmdType == VBOXHGCMCMDTYPE_CONNECT)
     367                pCmd->u.connect.pLoc = (HGCMServiceLocation *)(pCmd + 1);
    328368        }
    329         else if (enmCmdType == VBOXHGCMCMDTYPE_CONNECT)
    330             pCmd->u.connect.pLoc = (HGCMServiceLocation *)(pCmd + 1);
    331     }
    332     return pCmd;
     369        Log3Func(("returns %p (enmCmdType=%d GCPhys=%RGp cbCmd=%#x)\n", pCmd, enmCmdType, GCPhys, cbCmd));
     370        return pCmd;
     371    }
     372    LogFunc(("Heap budget overrun: cbCmd=%#x aHgcmAcc[%zu].cbHeapBudget=%#RX64 - enmCmdType=%d\n",
     373             cbCmd, idxHeapAcc, pThisCC->aHgcmAcc[idxHeapAcc].cbHeapBudget, enmCmdType));
     374    return NULL;
    333375}
    334376
     
    336378 *
    337379 * @param   pDevIns         The device instance.
     380 * @param   pThis           The VMMDev shared instance data.
    338381 * @param   pThisCC         The VMMDev ring-3 instance data.
    339382 * @param   pCmd            Command to deallocate.
    340383 */
    341 static void vmmdevR3HgcmCmdFree(PPDMDEVINS pDevIns, PVMMDEVCC pThisCC, PVBOXHGCMCMD pCmd)
     384static void vmmdevR3HgcmCmdFree(PPDMDEVINS pDevIns, PVMMDEV pThis, PVMMDEVCC pThisCC, PVBOXHGCMCMD pCmd)
    342385{
    343386    if (pCmd)
    344387    {
     388        Assert(   pCmd->enmCmdType == VBOXHGCMCMDTYPE_CALL
     389               || pCmd->enmCmdType == VBOXHGCMCMDTYPE_CONNECT
     390               || pCmd->enmCmdType == VBOXHGCMCMDTYPE_DISCONNECT
     391               || pCmd->enmCmdType == VBOXHGCMCMDTYPE_LOADSTATE);
    345392        if (pCmd->enmCmdType == VBOXHGCMCMDTYPE_CALL)
    346393        {
     
    390437        }
    391438
     439        pCmd->enmCmdType = UINT8_MAX; /* poison */
     440
     441        /* Update heap budget.  Need the critsect to do this safely. */
     442        Assert(pCmd->cbHeapCost != 0);
     443        uintptr_t idx = pCmd->idxHeapAcc;
     444        AssertStmt(idx < RT_ELEMENTS(pThisCC->aHgcmAcc), idx %= RT_ELEMENTS(pThisCC->aHgcmAcc));
     445
     446        PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
     447
     448        Log5Func(("aHgcmAcc[%zu] %#RX64 += %#x (%p)\n", idx, pThisCC->aHgcmAcc[idx].cbHeapBudget, pCmd->cbHeapCost, pCmd));
     449        pThisCC->aHgcmAcc[idx].cbHeapBudget += pCmd->cbHeapCost;
     450        AssertMsg(pThisCC->aHgcmAcc[idx].cbHeapBudget <= pThisCC->aHgcmAcc[idx].cbHeapBudgetConfig,
     451                  ("idx=%d (%d) fRequestor=%#x pCmd=%p: %#RX64 vs %#RX64 -> %#RX64\n", idx, pCmd->idxHeapAcc, pCmd->fRequestor, pCmd,
     452                   pThisCC->aHgcmAcc[idx].cbHeapBudget,  pThisCC->aHgcmAcc[idx].cbHeapBudgetConfig,
     453                   pThisCC->aHgcmAcc[idx].cbHeapBudget - pThisCC->aHgcmAcc[idx].cbHeapBudgetConfig));
     454        pCmd->cbHeapCost = 0;
     455
    392456#if 1
    393457        if (pCmd->fMemCache)
     458        {
    394459            RTMemCacheFree(pThisCC->hHgcmCmdCache, pCmd);
     460            PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); /* releasing it after just to be on the safe side. */
     461        }
    395462        else
    396463#endif
     464        {
     465            PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
    397466            RTMemFree(pCmd);
     467        }
    398468    }
    399469}
     
    415485
    416486    RTListPrepend(&pThisCC->listHGCMCmd, &pCmd->node);
     487
     488    /* stats */
     489    uintptr_t idx = pCmd->idxHeapAcc;
     490    AssertStmt(idx < RT_ELEMENTS(pThisCC->aHgcmAcc), idx %= RT_ELEMENTS(pThisCC->aHgcmAcc));
     491    STAM_REL_COUNTER_ADD(&pThisCC->aHgcmAcc[idx].cbHeapTotal, pCmd->cbHeapCost);
     492    STAM_REL_COUNTER_INC(&pThisCC->aHgcmAcc[idx].cTotalMessages);
    417493
    418494    /* Automatically enable HGCM events, if there are HGCM commands. */
     
    683759 * @returns VBox status code that the guest should see.
    684760 * @param   pDevIns         The device instance.
     761 * @param   pThisCC         The VMMDev ring-3 instance data.
    685762 * @param   pCmd            Command structure where host parameters needs initialization.
    686763 * @param   pbReq           The request buffer.
    687764 */
    688 static int vmmdevR3HgcmInitHostParameters(PPDMDEVINS pDevIns, PVBOXHGCMCMD pCmd, uint8_t const *pbReq)
     765static int vmmdevR3HgcmInitHostParameters(PPDMDEVINS pDevIns, PVMMDEVCC pThisCC, PVBOXHGCMCMD pCmd, uint8_t const *pbReq)
    689766{
    690767    AssertReturn(pCmd->enmCmdType == VBOXHGCMCMDTYPE_CALL, VERR_INTERNAL_ERROR);
     
    728805                {
    729806                    /* Zero memory, the buffer content is potentially copied to the guest. */
    730                     void *pv = RTMemAllocZ(cbData);
     807                    void *pv = vmmdevR3HgcmCallMemAllocZ(pThisCC, pCmd, cbData);
    731808                    AssertReturn(pv, VERR_NO_MEMORY);
    732809                    pHostParm->u.pointer.addr = pv;
     
    831908}
    832909
     910/**
     911 * Heap budget wrapper around RTMemAlloc and RTMemAllocZ.
     912 */
     913static void *vmmdevR3HgcmCallMemAllocEx(PVMMDEVCC pThisCC, PVBOXHGCMCMD pCmd, size_t cbRequested, bool fZero)
     914{
     915    /* Check against max heap costs for this request. */
     916    Assert(pCmd->cbHeapCost <= VMMDEV_MAX_HGCM_DATA_SIZE);
     917    if (cbRequested <= VMMDEV_MAX_HGCM_DATA_SIZE - pCmd->cbHeapCost)
     918    {
     919        /* Check heap budget (we're under lock). */
     920        uintptr_t idx = pCmd->idxHeapAcc;
     921        AssertStmt(idx < RT_ELEMENTS(pThisCC->aHgcmAcc), idx %= RT_ELEMENTS(pThisCC->aHgcmAcc));
     922        if (cbRequested <= pThisCC->aHgcmAcc[idx].cbHeapBudget)
     923        {
     924            /* Do the actual allocation. */
     925            void *pv = fZero ? RTMemAllocZ(cbRequested) : RTMemAlloc(cbRequested);
     926            if (pv)
     927            {
     928                /* Update the request cost and heap budget. */
     929                Log5Func(("aHgcmAcc[%zu] %#RX64 += %#x (%p)\n", idx, pThisCC->aHgcmAcc[idx].cbHeapBudget, cbRequested, pCmd));
     930                pThisCC->aHgcmAcc[idx].cbHeapBudget -=           cbRequested;
     931                pCmd->cbHeapCost                    += (uint32_t)cbRequested;
     932                return pv;
     933            }
     934            LogFunc(("Heap alloc failed: cbRequested=%#zx - enmCmdType=%d\n", cbRequested, pCmd->enmCmdType));
     935        }
     936        else
     937            LogFunc(("Heap budget overrun: cbRequested=%#zx cbHeapCost=%#x aHgcmAcc[%u].cbHeapBudget=%#RX64 - enmCmdType=%d\n",
     938                     cbRequested, pCmd->cbHeapCost, pCmd->idxHeapAcc, pThisCC->aHgcmAcc[idx].cbHeapBudget, pCmd->enmCmdType));
     939    }
     940    else
     941        LogFunc(("Request too big: cbRequested=%#zx cbHeapCost=%#x - enmCmdType=%d\n",
     942                 cbRequested, pCmd->cbHeapCost, pCmd->enmCmdType));
     943    return NULL;
     944}
     945
     946/**
     947 * Heap budget wrapper around RTMemAlloc.
     948 */
     949DECLINLINE(void *) vmmdevR3HgcmCallMemAlloc(PVMMDEVCC pThisCC, PVBOXHGCMCMD pCmd, size_t cbRequested)
     950{
     951    return vmmdevR3HgcmCallMemAllocEx(pThisCC, pCmd, cbRequested, false /*fZero*/);
     952}
     953
     954/**
     955 * Heap budget wrapper around RTMemAllocZ.
     956 */
     957DECLINLINE(void *) vmmdevR3HgcmCallMemAllocZ(PVMMDEVCC pThisCC, PVBOXHGCMCMD pCmd, size_t cbRequested)
     958{
     959    return vmmdevR3HgcmCallMemAllocEx(pThisCC, pCmd, cbRequested, true /*fZero*/);
     960}
     961
    833962/** Copy VMMDevHGCMCall request data from the guest to VBOXHGCMCMD command.
    834963 *
     
    864993    const uint8_t *pu8HGCMParm = (uint8_t *)pHGCMCall + offHGCMParms;
    865994
    866     uint32_t cbTotalData = 0;
    867995    for (uint32_t i = 0; i < cParms; ++i, pu8HGCMParm += cbHGCMParmStruct)
    868996    {
     
    9271055                LogFunc(("LinAddr guest parameter %RGv, cb %u\n", GCPtr, cbData));
    9281056
    929                 ASSERT_GUEST_RETURN(cbData <= VMMDEV_MAX_HGCM_DATA_SIZE - cbTotalData, VERR_INVALID_PARAMETER);
    930                 cbTotalData += cbData;
     1057                ASSERT_GUEST_RETURN(cbData <= VMMDEV_MAX_HGCM_DATA_SIZE, VERR_INVALID_PARAMETER);
    9311058
    9321059                const uint32_t offFirstPage = cbData > 0 ? GCPtr & PAGE_OFFSET_MASK : 0;
     
    9441071                    else
    9451072                    {
    946                         pGuestParm->u.ptr.paPages = (RTGCPHYS *)RTMemAlloc(cPages * sizeof(RTGCPHYS));
     1073                        /* (Max 262144 bytes with current limits.) */
     1074                        pGuestParm->u.ptr.paPages = (RTGCPHYS *)vmmdevR3HgcmCallMemAlloc(pThisCC, pCmd,
     1075                                                                                         cPages * sizeof(RTGCPHYS));
    9471076                        AssertReturn(pGuestParm->u.ptr.paPages, VERR_NO_MEMORY);
    9481077                    }
     
    9861115                LogFunc(("PageList guest parameter cb %u, offset %u\n", cbData, offPageListInfo));
    9871116
    988                 ASSERT_GUEST_RETURN(cbData <= VMMDEV_MAX_HGCM_DATA_SIZE - cbTotalData, VERR_INVALID_PARAMETER);
    989                 cbTotalData += cbData;
     1117                ASSERT_GUEST_RETURN(cbData <= VMMDEV_MAX_HGCM_DATA_SIZE, VERR_INVALID_PARAMETER);
    9901118
    9911119/** @todo respect zero byte page lists...    */
     
    10481176                    pGuestParm->u.Pages.cPages       = (uint16_t)cPages;
    10491177                    pGuestParm->u.Pages.fLocked      = false;
    1050                     pGuestParm->u.Pages.paPgLocks    = (PPGMPAGEMAPLOCK)RTMemAllocZ(  (sizeof(PGMPAGEMAPLOCK) + sizeof(void *))
    1051                                                                                     * cPages);
     1178                    pGuestParm->u.Pages.paPgLocks    = (PPGMPAGEMAPLOCK)vmmdevR3HgcmCallMemAllocZ(pThisCC, pCmd,
     1179                                                                                                  (  sizeof(PGMPAGEMAPLOCK)
     1180                                                                                                   + sizeof(void *)) * cPages);
    10521181                    AssertReturn(pGuestParm->u.Pages.paPgLocks, VERR_NO_MEMORY);
    10531182
     
    10901219                else
    10911220                {
    1092                     pGuestParm->u.ptr.paPages   = (RTGCPHYS *)RTMemAlloc(pPageListInfo->cPages * sizeof(RTGCPHYS));
     1221                    pGuestParm->u.ptr.paPages   = (RTGCPHYS *)vmmdevR3HgcmCallMemAlloc(pThisCC, pCmd,
     1222                                                                                       pPageListInfo->cPages * sizeof(RTGCPHYS));
    10931223                    AssertReturn(pGuestParm->u.ptr.paPages, VERR_NO_MEMORY);
    10941224
     
    11131243                LogFunc(("Embedded guest parameter cb %u, offset %u, flags %#x\n", cbData, offData, fFlags));
    11141244
    1115                 ASSERT_GUEST_RETURN(cbData <= VMMDEV_MAX_HGCM_DATA_SIZE - cbTotalData, VERR_INVALID_PARAMETER);
    1116                 cbTotalData += cbData;
     1245                ASSERT_GUEST_RETURN(cbData <= VMMDEV_MAX_HGCM_DATA_SIZE, VERR_INVALID_PARAMETER);
    11171246
    11181247                /* Check flags and buffer range. */
     
    11971326        {
    11981327            /* Copy guest data to host parameters, so HGCM services can use the data. */
    1199             rc = vmmdevR3HgcmInitHostParameters(pDevIns, pCmd, (uint8_t const *)pHGCMCall);
     1328            rc = vmmdevR3HgcmInitHostParameters(pDevIns, pThisCC, pCmd, (uint8_t const *)pHGCMCall);
    12001329            if (RT_SUCCESS(rc))
    12011330            {
     
    12551384            }
    12561385        }
    1257         vmmdevR3HgcmCmdFree(pDevIns, pThisCC, pCmd);
     1386        vmmdevR3HgcmCmdFree(pDevIns, pThis, pThisCC, pCmd);
    12581387    }
    12591388    return rc;
     
    16881817#endif
    16891818
    1690     /* Deallocate the command memory. */
     1819    /* Deallocate the command memory. Enter the critsect for proper  */
    16911820    VBOXDD_HGCMCALL_COMPLETED_DONE(pCmd, idFunction, idClient, result);
    1692     vmmdevR3HgcmCmdFree(pDevIns, pThisCC, pCmd);
     1821    vmmdevR3HgcmCmdFree(pDevIns, pThis, pThisCC, pCmd);
    16931822
    16941823#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
     
    20042133                                AssertReturn(   pGuestParm->enmType != VMMDevHGCMParmType_Embedded
    20052134                                             && pGuestParm->enmType != VMMDevHGCMParmType_ContiguousPageList, VERR_INTERNAL_ERROR_3);
    2006                                 pPtr->paPages = (RTGCPHYS *)RTMemAlloc(pPtr->cPages * sizeof(RTGCPHYS));
     2135                                pPtr->paPages = (RTGCPHYS *)vmmdevR3HgcmCallMemAlloc(pThisCC, pCmd,
     2136                                                                                     pPtr->cPages * sizeof(RTGCPHYS));
    20072137                                AssertStmt(pPtr->paPages, rc = VERR_NO_MEMORY);
    20082138                            }
     
    20642194                Log(("vmmdevR3HgcmLoadState: Skipping cancelled request: enmCmdType=%d GCPhys=%#RX32 LB %#x\n",
    20652195                     enmCmdType, GCPhys, cbRequest));
    2066                 vmmdevR3HgcmCmdFree(pDevIns, pThisCC, pCmd);
     2196                vmmdevR3HgcmCmdFree(pDevIns, pThis, pThisCC, pCmd);
    20672197            }
    20682198        }
     
    21282258                    AssertRCReturn(rc, rc);
    21292259
    2130                     pPtr->paPages = (RTGCPHYS *)RTMemAlloc(pPtr->cPages * sizeof(RTGCPHYS));
     2260                    pPtr->paPages = (RTGCPHYS *)vmmdevR3HgcmCallMemAlloc(pThisCC, pCmd, pPtr->cPages * sizeof(RTGCPHYS));
    21312261                    AssertReturn(pPtr->paPages, VERR_NO_MEMORY);
    21322262
     
    21482278                Log(("vmmdevR3HgcmLoadState: Skipping cancelled request: enmCmdType=%d GCPhys=%#RX32 LB %#x\n",
    21492279                     enmCmdType, GCPhys, cbRequest));
    2150                 vmmdevR3HgcmCmdFree(pDevIns, pThisCC, pCmd);
     2280                vmmdevR3HgcmCmdFree(pDevIns, pThis, pThisCC, pCmd);
    21512281            }
    21522282        }
     
    22552385 * @returns VBox status code that the guest should see.
    22562386 * @param   pDevIns         The device instance.
     2387 * @param   pThis           The VMMDev shared instance data.
    22572388 * @param   pThisCC         The VMMDev ring-3 instance data.
    22582389 * @param   uSavedStateVersion   The saved state version the command has been loaded from.
     
    22632394 * @param   ppRestoredCmd   Where to store pointer to newly allocated restored command.
    22642395 */
    2265 static int vmmdevR3HgcmRestoreCall(PPDMDEVINS pDevIns, PVMMDEVCC pThisCC, uint32_t uSavedStateVersion, const VBOXHGCMCMD *pLoadedCmd,
    2266                                    VMMDevHGCMCall *pReq, uint32_t cbReq, VMMDevRequestType enmRequestType,
    2267                                    VBOXHGCMCMD **ppRestoredCmd)
     2396static int vmmdevR3HgcmRestoreCall(PPDMDEVINS pDevIns, PVMMDEV pThis, PVMMDEVCC pThisCC, uint32_t uSavedStateVersion,
     2397                                   const VBOXHGCMCMD *pLoadedCmd, VMMDevHGCMCall *pReq, uint32_t cbReq,
     2398                                   VMMDevRequestType enmRequestType, VBOXHGCMCMD **ppRestoredCmd)
    22682399{
    22692400    /* Verify the request.  */
     
    23152446        *ppRestoredCmd = pCmd;
    23162447    else
    2317         vmmdevR3HgcmCmdFree(pDevIns, pThisCC, pCmd);
     2448        vmmdevR3HgcmCmdFree(pDevIns, pThis, pThisCC, pCmd);
    23182449
    23192450    return rc;
     
    23252456 * @returns VBox status code that the guest should see.
    23262457 * @param   pDevIns         The device instance.
     2458 * @param   pThis           The VMMDev shared instance data.
    23272459 * @param   pThisCC         The VMMDev ring-3 instance data.
    23282460 * @param   uSavedStateVersion   Saved state version.
     
    23322464 * @param   ppRestoredCmd   Where to store pointer to restored command.
    23332465 */
    2334 static int vmmdevR3HgcmRestoreCommand(PPDMDEVINS pDevIns, PVMMDEVCC pThisCC, uint32_t uSavedStateVersion,
     2466static int vmmdevR3HgcmRestoreCommand(PPDMDEVINS pDevIns, PVMMDEV pThis, PVMMDEVCC pThisCC, uint32_t uSavedStateVersion,
    23352467                                      const VBOXHGCMCMD *pLoadedCmd, const VMMDevHGCMRequestHeader *pReqHdr, uint32_t cbReq,
    23362468                                      VBOXHGCMCMD **ppRestoredCmd)
     
    23652497        {
    23662498            VMMDevHGCMCall *pReq = (VMMDevHGCMCall *)pReqHdr;
    2367             rc = vmmdevR3HgcmRestoreCall(pDevIns, pThisCC, uSavedStateVersion, pLoadedCmd, pReq, cbReq, enmRequestType, ppRestoredCmd);
     2499            rc = vmmdevR3HgcmRestoreCall(pDevIns, pThis, pThisCC, uSavedStateVersion, pLoadedCmd,
     2500                                         pReq, cbReq, enmRequestType, ppRestoredCmd);
    23682501            break;
    23692502        }
     
    24252558         */
    24262559        VMMDevHGCMRequestHeader *pReqHdr = (VMMDevHGCMRequestHeader *)RTMemAlloc(pCmd->cbRequest);
    2427         AssertBreakStmt(pReqHdr, vmmdevR3HgcmCmdFree(pDevIns, pThisCC, pCmd); rcFunc = VERR_NO_MEMORY);
     2560        AssertBreakStmt(pReqHdr, vmmdevR3HgcmCmdFree(pDevIns, pThis, pThisCC, pCmd); rcFunc = VERR_NO_MEMORY);
    24282561
    24292562        PDMDevHlpPhysRead(pDevIns, pCmd->GCPhys, pReqHdr, pCmd->cbRequest);
     
    24412574            {
    24422575                PVBOXHGCMCMD pRestoredCmd = NULL;
    2443                 rcCmd = vmmdevR3HgcmRestoreCommand(pDevIns, pThisCC, pThisCC->uSavedStateVersion, pCmd,
     2576                rcCmd = vmmdevR3HgcmRestoreCommand(pDevIns, pThis, pThisCC, pThisCC->uSavedStateVersion, pCmd,
    24442577                                                   pReqHdr, pCmd->cbRequest, &pRestoredCmd);
    24452578                if (RT_SUCCESS(rcCmd))
    24462579                {
    24472580                    Assert(pCmd != pRestoredCmd); /* vmmdevR3HgcmRestoreCommand must allocate restored command. */
    2448                     vmmdevR3HgcmCmdFree(pDevIns, pThisCC, pCmd);
     2581                    vmmdevR3HgcmCmdFree(pDevIns, pThis, pThisCC, pCmd);
    24492582                    pCmd = pRestoredCmd;
    24502583                }
     
    24772610                    case VBOXHGCMCMDTYPE_CALL:
    24782611                    {
    2479                         rcCmd = vmmdevR3HgcmInitHostParameters(pDevIns, pCmd, (uint8_t const *)pReqHdr);
     2612                        rcCmd = vmmdevR3HgcmInitHostParameters(pDevIns, pThisCC, pCmd, (uint8_t const *)pReqHdr);
    24802613                        if (RT_SUCCESS(rcCmd))
    24812614                        {
     
    25202653
    25212654            /* Deallocate the command memory. */
    2522             vmmdevR3HgcmCmdFree(pDevIns, pThisCC, pCmd);
     2655            vmmdevR3HgcmCmdFree(pDevIns, pThis, pThisCC, pCmd);
    25232656        }
    25242657
     
    25312664        {
    25322665            RTListNodeRemove(&pCmd->node);
    2533             vmmdevR3HgcmCmdFree(pDevIns, pThisCC, pCmd);
     2666            vmmdevR3HgcmCmdFree(pDevIns, pThis, pThisCC, pCmd);
    25342667        }
    25352668    }
     
    25432676 *
    25442677 * @param   pDevIns         The device instance.
     2678 * @param   pThis           The VMMDev shared instance data.
    25452679 * @param   pThisCC         The VMMDev ring-3 instance data.
    25462680 */
    2547 void vmmdevR3HgcmDestroy(PPDMDEVINS pDevIns, PVMMDEVCC pThisCC)
     2681void vmmdevR3HgcmDestroy(PPDMDEVINS pDevIns, PVMMDEV pThis, PVMMDEVCC pThisCC)
    25482682{
    25492683    LogFlowFunc(("\n"));
     
    25552689        {
    25562690            vmmdevR3HgcmRemoveCommand(pThisCC, pCmd);
    2557             vmmdevR3HgcmCmdFree(pDevIns, pThisCC, pCmd);
     2691            vmmdevR3HgcmCmdFree(pDevIns, pThis, pThisCC, pCmd);
    25582692        }
    25592693
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.h

    r82968 r90264  
    4545int  vmmdevR3HgcmLoadStateDone(PPDMDEVINS pDevIns, PVMMDEV pThis, PVMMDEVCC pThisCC);
    4646
    47 void vmmdevR3HgcmDestroy(PPDMDEVINS pDevIns, PVMMDEVCC pThisCC);
     47void vmmdevR3HgcmDestroy(PPDMDEVINS pDevIns, PVMMDEV pThis, PVMMDEVCC pThisCC);
    4848int  vmmdevR3HgcmInit(PVMMDEVCC pThisCC);
    4949RT_C_DECLS_END
  • trunk/src/VBox/Devices/VMMDev/VMMDevState.h

    r82968 r90264  
    400400    uint32_t                        uSavedStateVersion;
    401401    RTMEMCACHE                      hHgcmCmdCache;
     402    /** Accounting by for each requestor VMMDEV_REQUESTOR_USR_XXX group.
     403     * Legacy requests ends up with VMMDEV_REQUESTOR_USR_NOT_GIVEN */
     404    struct
     405    {
     406        /** The configured heap budget. */
     407        uint64_t                    cbHeapBudgetConfig;
     408        /** The currently available heap budget.   */
     409        uint64_t                    cbHeapBudget;
     410        /** Total sum of all heap usage.   */
     411        STAMCOUNTER                 cbHeapTotal;
     412        /** Total number of message. */
     413        STAMCOUNTER                 cTotalMessages;
     414    } aHgcmAcc[VMMDEV_REQUESTOR_USR_MASK + 1];
    402415    STAMPROFILE                     StatHgcmCmdArrival;
    403416    STAMPROFILE                     StatHgcmCmdCompletion;
Note: See TracChangeset for help on using the changeset viewer.

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