VirtualBox

Changeset 26999 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 3, 2010 5:00:05 PM (15 years ago)
Author:
vboxsync
Message:

Guest Additions: memory ballooning for guests without support for RTR0MemObjAllocPhysNC() (does not work yet)

Location:
trunk/src/VBox/Additions
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxGuest/VBoxGuest.cpp

    r26922 r26999  
    745745        if (RT_FAILURE(rc))
    746746        {
    747             dprintf(("VBoxGuest::VBoxGuestDeviceControl VBOXGUEST_IOCTL_CTL_CHECK_BALLOON: error issuing request to VMMDev! "
     747            dprintf(("VBoxGuest::VBoxGuestDeviceControl VBOXGUEST_IOCTL_CHECK_BALLOON: error issuing request to VMMDev! "
    748748                     "rc = %Rrc\n", rc));
    749749        }
     
    13801380
    13811381#ifdef VBOX_WITH_MANAGEMENT
    1382         case VBOXGUEST_IOCTL_CTL_CHECK_BALLOON_MASK:
     1382        case VBOXGUEST_IOCTL_CHECK_BALLOON:
    13831383        {
    13841384            ULONG *pMemBalloonSize = (ULONG *) pBuf;
     
    13951395            if (RT_FAILURE(rc))
    13961396            {
    1397                 dprintf(("VBOXGUEST_IOCTL_CTL_CHECK_BALLOON: vbox rc = %Rrc\n", rc));
     1397                dprintf(("VBOXGUEST_IOCTL_CHECK_BALLOON: vbox rc = %Rrc\n", rc));
    13981398                Status = STATUS_UNSUCCESSFUL;
    13991399            }
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp

    r26934 r26999  
    276276
    277277/**
    278  * Infltate/deflate the memory balloon and notify the host.
     278 * Inflate/deflate the memory balloon and notify the host.
    279279 *
    280280 * @returns VBox status code.
     
    282282 * @param   u32BalloonSize The new size of the balloon in chunks of 1MB.
    283283 */
    284 static int vboxGuestSetBalloonSize(PVBOXGUESTDEVEXT pDevExt, uint32_t u32BalloonSize)
    285 {
    286     VMMDevChangeMemBalloon *pReq;
     284static int vboxGuestSetBalloonSizeKernel(PVBOXGUESTDEVEXT pDevExt, uint32_t u32BalloonSize)
     285{
    287286    int rc = VINF_SUCCESS;
    288     uint32_t i, j;
    289     const size_t cbReq = RT_OFFSETOF(VMMDevChangeMemBalloon, aPhysPage[VMMDEV_MEMORY_BALLOON_CHUNK_PAGES]);
    290 
    291     if (u32BalloonSize > pDevExt->MemBalloon.cMaxChunks)
    292     {
    293         AssertMsgFailed(("vboxGuestSetBalloonSize illegal balloon size %d (max=%d)\n",
    294                          u32BalloonSize, pDevExt->MemBalloon.cMaxChunks));
    295         return VERR_INVALID_PARAMETER;
    296     }
    297 
    298     if (u32BalloonSize == pDevExt->MemBalloon.cMaxChunks)
    299         return VINF_SUCCESS;   /* nothing to do */
    300 
    301     rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, cbReq, VMMDevReq_ChangeMemBalloon);
    302     if (RT_FAILURE(rc))
    303         return rc;
    304287
    305288    if (pDevExt->MemBalloon.fUseKernelAPI)
    306289    {
     290        VMMDevChangeMemBalloon *pReq;
     291        uint32_t i, j;
     292        const size_t cbReq = RT_OFFSETOF(VMMDevChangeMemBalloon, aPhysPage[VMMDEV_MEMORY_BALLOON_CHUNK_PAGES]);
     293
     294        if (u32BalloonSize > pDevExt->MemBalloon.cMaxChunks)
     295        {
     296            AssertMsgFailed(("vboxGuestSetBalloonSize illegal balloon size %d (max=%d)\n",
     297                             u32BalloonSize, pDevExt->MemBalloon.cMaxChunks));
     298            return VERR_INVALID_PARAMETER;
     299        }
     300
     301        if (u32BalloonSize == pDevExt->MemBalloon.cMaxChunks)
     302            return VINF_SUCCESS;   /* nothing to do */
     303
     304        rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, cbReq, VMMDevReq_ChangeMemBalloon);
     305        if (RT_FAILURE(rc))
     306            return rc;
     307
    307308        if (u32BalloonSize > pDevExt->MemBalloon.cChunks)
    308309        {
     
    381382            }
    382383        }
     384
     385        VbglGRFree(&pReq->header);
    383386    }
    384387
    385388    if (!pDevExt->MemBalloon.fUseKernelAPI)
    386389    {
    387         /* R3 to allocate memory, R0 to lock it down and tell the host */
    388     }
     390        /* R3 to allocate memory, then do ioctl(VBOXGUEST_IOCTL_CHANGE_BALLOON)
     391         * and R0 to lock it down and tell the host. */
     392        rc = VERR_NO_PHYS_MEMORY;
     393    }
     394
     395    return rc;
     396}
     397
     398
     399/**
     400 * Inflate/deflate the balloon by one chunk.
     401 */
     402static int vboxGuestSetBalloonSizeFromUser(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
     403                                           uint64_t u64ChunkAddr, bool fInflate)
     404{
     405    VMMDevChangeMemBalloon *pReq;
     406    int rc = VINF_SUCCESS;
     407    uint32_t i, j;
     408    const size_t cbReq = RT_OFFSETOF(VMMDevChangeMemBalloon, aPhysPage[VMMDEV_MEMORY_BALLOON_CHUNK_PAGES]);
     409    PRTR0MEMOBJ pMemObj = NULL;
     410
     411    if (   fInflate
     412        && pSession->MemBalloon.cChunks > pSession->MemBalloon.cMaxChunks - 1)
     413    {
     414        AssertMsgFailed(("vboxGuestSetBalloonSize: cannot inflate balloon, already have (max=%d)\n",
     415                         pSession->MemBalloon.cChunks, pSession->MemBalloon.cMaxChunks));
     416        return VERR_INVALID_PARAMETER;
     417    }
     418    else if (   !fInflate
     419             && pSession->MemBalloon.cChunks == 0)
     420    {
     421        AssertMsgFailed(("vboxGuestSetBalloonSize: cannot decrease balloon, already at size 0\n"));
     422        return VERR_INVALID_PARAMETER;
     423    }
     424
     425    /*
     426     * Enumerate all memory objects and check if the object is already registered.
     427     */
     428    for (i = 0; i < pSession->MemBalloon.cMaxChunks; i++)
     429    {
     430        if (   fInflate
     431            && !pSession->MemBalloon.paMemObj[i] == NIL_RTR0MEMOBJ
     432            && !pMemObj)
     433            pMemObj = &pSession->MemBalloon.paMemObj[i]; /* found free object pointer */
     434        if (RTR0MemObjAddressR3(pSession->MemBalloon.paMemObj[i]) == u64ChunkAddr)
     435        {
     436            if (fInflate)
     437                return VERR_ALREADY_EXISTS; /* don't provide the same memory twice */
     438            pMemObj = &pSession->MemBalloon.paMemObj[i];
     439            break;
     440        }
     441    }
     442    if (!pMemObj)
     443    {
     444        if (fInflate)
     445            return VERR_NO_MEMORY; /* no free object pointer found -- should not happen */
     446        else
     447            return VERR_NOT_FOUND; /* cannot free this memory as it wasn't provided before */
     448    }
     449
     450    rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, cbReq, VMMDevReq_ChangeMemBalloon);
     451    if (RT_FAILURE(rc))
     452        return rc;
     453
     454    do
     455    {
     456        if (fInflate)
     457        {
     458            rc = RTR0MemObjLockUser(pMemObj, u64ChunkAddr, VMMDEV_MEMORY_BALLOON_CHUNK_PAGES * PAGE_SIZE,
     459                                    RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
     460            if (RT_SUCCESS(rc))
     461            {
     462                RTR0MEMOBJ MemObj = pDevExt->MemBalloon.paMemObj[i];
     463                for (j = 0; j < VMMDEV_MEMORY_BALLOON_CHUNK_PAGES; j++)
     464                {
     465                    RTHCPHYS phys = RTR0MemObjGetPagePhysAddr(MemObj, j);
     466                    pReq->aPhysPage[j] = phys;
     467                }
     468
     469                pReq->header.size = cbReq;
     470                pReq->cPages = VMMDEV_MEMORY_BALLOON_CHUNK_PAGES;
     471                pReq->fInflate = true;
     472
     473                rc = VbglGRPerform(&pReq->header);
     474                if (RT_FAILURE(rc))
     475                {
     476                    Log(("vboxGuestSetBalloonSize(inflate): VbglGRPerform failed, rc=%Rrc!\n", rc));
     477                    break;
     478                }
     479                pSession->MemBalloon.cChunks++;
     480            }
     481        }
     482        else
     483        {
     484            /* deflate */
     485            for (j = 0; j < VMMDEV_MEMORY_BALLOON_CHUNK_PAGES; j++)
     486            {
     487                RTHCPHYS phys = RTR0MemObjGetPagePhysAddr(*pMemObj, j);
     488                pReq->aPhysPage[j] = phys;
     489            }
     490
     491            pReq->header.size = cbReq;
     492            pReq->cPages = VMMDEV_MEMORY_BALLOON_CHUNK_PAGES;
     493            pReq->fInflate = false;
     494
     495            rc = VbglGRPerform(&pReq->header);
     496            if (RT_FAILURE(rc))
     497            {
     498                Log(("vboxGuestSetBalloonSize(deflate): VbglGRPerform failed, rc=%Rrc!\n", rc));
     499                break;
     500            }
     501
     502            rc = RTR0MemObjFree(*pMemObj, true);
     503            if (RT_FAILURE(rc))
     504            {
     505                Log(("vboxGuestSetBalloonSize(deflate): RTR0MemObjFree() failed, rc=%Rrc!\n", rc));
     506                break;
     507            }
     508            *pMemObj = NIL_RTR0MEMOBJ;
     509            pSession->MemBalloon.cChunks--;
     510        }
     511    } while (0);
    389512
    390513    VbglGRFree(&pReq->header);
     
    402525    pDevExt->MemBalloon.cChunks = 0;
    403526    pDevExt->MemBalloon.cMaxChunks = 0;
    404 #ifdef RT_OS_LINUX
    405     pDevExt->MemBalloon.fUseKernelAPI = true;
    406 #else
     527//#ifdef RT_OS_LINUX
     528//    pDevExt->MemBalloon.fUseKernelAPI = true;
     529//#else
    407530    pDevExt->MemBalloon.fUseKernelAPI = false;
    408 #endif
     531//#endif
    409532    pDevExt->MemBalloon.paMemObj = NULL;
    410533}
     
    420543    if (pDevExt->MemBalloon.paMemObj)
    421544    {
    422         vboxGuestSetBalloonSize(pDevExt, 0);
     545        vboxGuestSetBalloonSizeKernel(pDevExt, 0);
    423546        RTMemFree(pDevExt->MemBalloon.paMemObj);
    424547        pDevExt->MemBalloon.paMemObj = NULL;
     
    652775int VBoxGuestCreateUserSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION *ppSession)
    653776{
     777    unsigned i;
    654778    PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)RTMemAllocZ(sizeof(*pSession));
    655779    if (RT_UNLIKELY(!pSession))
     
    662786    pSession->R0Process = RTR0ProcHandleSelf();
    663787    pSession->pDevExt = pDevExt;
     788
     789    pSession->MemBalloon.cChunks = 0;
     790    pSession->MemBalloon.cMaxChunks = 0;
    664791
    665792    *ppSession = pSession;
     
    16121739
    16131740/**
    1614  * Handle VBOXGUEST_IOCTL_CTL_CHECK_BALLOON_MASK from R3. Ask the host for the size of
    1615  * the balloon and set it accordingly.
     1741 * Handle VBOXGUEST_IOCTL_CHECK_BALLOON from R3. Ask the host for the size
     1742 * of the balloon and try to set it accordingly. If this fails, return with
     1743 * VERR_NO_PHYS_MEMORY and userland has to provide the memory.
    16161744 *
    16171745 * @returns VBox status code.
    16181746 */
    1619 static int VBoxGuestCommonIOCtl_QueryMemoryBalloon(PVBOXGUESTDEVEXT pDevExt, uint32_t *memBalloonSize, size_t *pcbDataReturned)
     1747static int VBoxGuestCommonIOCtl_QueryMemoryBalloon(PVBOXGUESTDEVEXT pDevExt,
     1748                                                   uint32_t *memBalloonSize, size_t *pcbDataReturned)
    16201749{
    16211750    VMMDevGetMemBalloonChangeRequest *pReq;
     
    16421771    }
    16431772
    1644     rc = vboxGuestSetBalloonSize(pDevExt, pReq->u32BalloonSize);
     1773    rc = vboxGuestSetBalloonSizeKernel(pDevExt, pReq->u32BalloonSize);
    16451774    /* ignore out of memory failures */
    16461775    if (rc == VERR_NO_MEMORY)
     
    16541783    return rc;
    16551784}
     1785
     1786
     1787/**
     1788 *
     1789 */
     1790static int VBoxGuestCommonIOCtl_ChangeMemoryBalloon(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
     1791                                                    VBoxGuestChangeBalloonInfo *pInfo, size_t *pcbDataReturned)
     1792{
     1793    int rc = vboxGuestSetBalloonSizeFromUser(pDevExt, pSession, pInfo->u64ChunkAddr, pInfo->fInflate);
     1794    if (pcbDataReturned)
     1795        *pcbDataReturned = 0;
     1796    return rc;
     1797}
     1798
    16561799
    16571800/**
     
    18331976#endif /* VBOX_WITH_HGCM */
    18341977
    1835             case VBOXGUEST_IOCTL_CTL_CHECK_BALLOON_MASK:
    1836                 CHECKRET_MIN_SIZE("MEMORY_BALLOON", sizeof(uint32_t));
     1978            case VBOXGUEST_IOCTL_CHECK_BALLOON:
     1979                CHECKRET_MIN_SIZE("CHECK_MEMORY_BALLOON", sizeof(uint32_t));
    18371980                rc = VBoxGuestCommonIOCtl_QueryMemoryBalloon(pDevExt, (uint32_t *)pvData, pcbDataReturned);
     1981                break;
     1982
     1983            case VBOXGUEST_IOCTL_CHANGE_BALLOON:
     1984                CHECKRET_MIN_SIZE("CHANGE_MEMORY_BALLOON", sizeof(VBoxGuestChangeBalloonInfo));
     1985                rc = VBoxGuestCommonIOCtl_ChangeMemoryBalloon(pDevExt, pSession, (VBoxGuestChangeBalloonInfo *)pvData, pcbDataReturned);
    18381986                break;
    18391987
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h

    r26934 r26999  
    140140    uint32_t                    u32ClipboardClientId;
    141141
    142     /* Memory balloon information. */
     142    /* Memory balloon information for RTR0MemObjAllocPhysNC(). */
    143143    VBOXGUESTMEMBALLOON         MemBalloon;
    144144
     
    183183     * Used to implement polling.  */
    184184    uint32_t volatile           u32MousePosChangedSeq;
     185
     186    /* Memory ballooning information if userland provides the balloon memory. */
     187    VBOXGUESTMEMBALLOON         MemBalloon;
    185188} VBOXGUESTSESSION;
    186189
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibMisc.cpp

    r26493 r26999  
    240240VBGLR3DECL(int) VbglR3MemBalloonRefresh(uint32_t *pu32Size)
    241241{
    242     return vbglR3DoIOCtl(VBOXGUEST_IOCTL_CTL_CHECK_BALLOON_MASK, pu32Size, sizeof(*pu32Size));
     242    return vbglR3DoIOCtl(VBOXGUEST_IOCTL_CHECK_BALLOON, pu32Size, sizeof(*pu32Size));
     243}
     244
     245
     246/**
     247 *
     248 */
     249VBGLR3DECL(int) VbglR3MemBalloonChange(void *pv, bool fInflate)
     250{
     251    VBoxGuestChangeBalloonInfo Info;
     252    Info.u64ChunkAddr = (uint64_t)pv;
     253    Info.fInflate = fInflate;
     254    return vbglR3DoIOCtl(VBOXGUEST_IOCTL_CHANGE_BALLOON, &Info, sizeof(Info));
    243255}
    244256
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceBalloon.cpp

    r26904 r26999  
    2222#include <iprt/mem.h>
    2323#include <iprt/thread.h>
     24#include <iprt/stream.h>
    2425#include <iprt/string.h>
    2526#include <iprt/semaphore.h>
     
    4041static RTSEMEVENTMULTI  g_MemBalloonEvent = NIL_RTSEMEVENTMULTI;
    4142
     43static void **g_pavBalloon = NULL;
     44
     45
     46static void VBoxServiceBalloonSetUser(uint32_t OldSize, uint32_t NewSize)
     47{
     48    if (NewSize == OldSize)
     49        return;
     50
     51    int rc = VINF_SUCCESS;
     52    if (NewSize > OldSize)
     53    {
     54        /* inflate */
     55        uint32_t i;
     56        g_pavBalloon = (void**)RTMemRealloc(g_pavBalloon, NewSize * sizeof(void*));
     57        RTPrintf("allocated %d bytes\n", g_pavBalloon, NewSize * sizeof(void*));
     58        for (i = OldSize; i < NewSize; i++)
     59        {
     60            void *pv = RTMemAlloc(VMMDEV_MEMORY_BALLOON_CHUNK_PAGES * PAGE_SIZE);
     61            VBoxServiceVerbose(3, "Alloc %p\n", pv);
     62            rc = VbglR3MemBalloonChange(pv, /* inflate=*/ true);
     63            if (RT_SUCCESS(rc))
     64            {
     65                VBoxServiceVerbose(3, " => %Rrc\n", rc);
     66                g_pavBalloon[i] = pv;
     67                OldSize++;
     68            }
     69            else
     70                break;
     71        }
     72    }
     73    else
     74    {
     75        /* deflate */
     76        uint32_t i;
     77        for (i = OldSize; i > NewSize; i--)
     78        {
     79            void *pv = g_pavBalloon[i-1];
     80            rc = VbglR3MemBalloonChange(pv, /* inflate=*/ false);
     81            if (RT_SUCCESS(rc))
     82            {
     83                VBoxServiceVerbose(3, "Free %p\n", g_pavBalloon[i-1]);
     84                RTMemFree(g_pavBalloon[i-1]);
     85                g_pavBalloon[i-1] = NULL;
     86                OldSize--;
     87            }
     88            else
     89                break;
     90        }
     91    }
     92
     93    if (RT_FAILURE(rc))
     94        g_MemBalloonSize = OldSize;
     95}
     96
     97
    4298/** @copydoc VBOXSERVICE::pfnPreInit */
    4399static DECLCALLBACK(int) VBoxServiceBalloonPreInit(void)
     
    68124    if (RT_SUCCESS(rc))
    69125        VBoxServiceVerbose(3, "VBoxMemBalloonInit: new balloon size %d MB\n", g_MemBalloonSize);
     126    else if (rc == VERR_NO_PHYS_MEMORY)
     127        VBoxServiceBalloonSetUser(0, g_MemBalloonSize);
    70128    else
    71129        VBoxServiceVerbose(3, "VBoxMemBalloonInit: VbglR3MemBalloonRefresh failed with %d\n", rc);
     
    113171            &&  (fEvents & VMMDEV_EVENT_BALLOON_CHANGE_REQUEST))
    114172        {
     173            uint32_t OldMemBalloonSize = g_MemBalloonSize;
    115174            rc = VbglR3MemBalloonRefresh(&g_MemBalloonSize);
    116175            if (RT_SUCCESS(rc))
    117176                VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: new balloon size %d MB\n", g_MemBalloonSize);
     177            else if (rc == VERR_NO_PHYS_MEMORY)
     178                VBoxServiceBalloonSetUser(OldMemBalloonSize, g_MemBalloonSize);
    118179            else
    119180                VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: VbglR3MemBalloonRefresh failed with %d\n", rc);
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