VirtualBox

Changeset 29424 in vbox


Ignore:
Timestamp:
May 12, 2010 3:11:09 PM (15 years ago)
Author:
vboxsync
Message:

Shared paging updates

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/gmm.h

    r29308 r29424  
    3131#include <VBox/sup.h>
    3232#include <VBox/VMMDev.h> /* for VMMDEVSHAREDREGIONDESC */
    33 
     33#include <iprt/avl.h>
    3434RT_C_DECLS_BEGIN
    3535
     
    279279#endif
    280280
     281
    281282GMMR0DECL(int)  GMMR0Init(void);
    282283GMMR0DECL(void) GMMR0Term(void);
     
    297298GMMR0DECL(int)  GMMR0UnregisterSharedModule(PVM pVM, VMCPUID idCpu, char *pszModuleName, char *pszVersion, RTGCPTR GCBaseAddr, uint32_t cbModule);
    298299GMMR0DECL(int)  GMMR0UnregisterAllSharedModules(PVM pVM, VMCPUID idCpu);
     300GMMR0DECL(int)  GMMR0CheckSharedModules(PVM pVM, VMCPUID idCpu);
    299301GMMR0DECL(int)  GMMR0ResetSharedModules(PVM pVM, VMCPUID idCpu);
    300302
     
    495497
    496498/**
     499 * Shared region descriptor
     500 */
     501typedef struct GMMSHAREDREGIONDESC
     502{
     503    /** Region base address. */
     504    RTGCPTR64           GCRegionAddr;
     505    /** Region size. */
     506    uint32_t            cbRegion;
     507    /** Alignment. */
     508    uint32_t            u32Alignment;
     509    /** Pointer to physical page id array. */
     510    uint32_t           *paHCPhysPageID;
     511} GMMSHAREDREGIONDESC;
     512/** Pointer to a GMMSHAREDREGIONDESC. */
     513typedef GMMSHAREDREGIONDESC *PGMMSHAREDREGIONDESC;
     514
     515
     516/**
     517 * Shared module registration info (global)
     518 */
     519typedef struct GMMSHAREDMODULE
     520{
     521    /* Tree node. */
     522    AVLGCPTRNODECORE            Core;
     523    /** Shared module size. */
     524    uint32_t                    cbModule;
     525    /** Number of included region descriptors */
     526    uint32_t                    cRegions;
     527    /** Number of users (VMs). */
     528    uint32_t                    cUsers;
     529    /** Guest OS family type. */
     530    VBOXOSFAMILY                enmGuestOS;
     531    /** Module name */
     532    char                        szName[GMM_SHARED_MODULE_MAX_NAME_STRING];
     533    /** Module version */
     534    char                        szVersion[GMM_SHARED_MODULE_MAX_VERSION_STRING];
     535    /** Shared region descriptor(s). */
     536    GMMSHAREDREGIONDESC         aRegions[1];
     537} GMMSHAREDMODULE;
     538/** Pointer to a GMMSHAREDMODULE. */
     539typedef GMMSHAREDMODULE *PGMMSHAREDMODULE;
     540
     541/**
    497542 * Page descriptor for GMMR0SharedModuleCheckRange
    498543 */
     
    511556typedef GMMSHAREDPAGEDESC *PGMMSHAREDPAGEDESC;
    512557
    513 GMMR0DECL(int) GMMR0SharedModuleCheckRange(PVM pVM, VMCPUID idCpu, PGMMREGISTERSHAREDMODULEREQ pReq, unsigned idxRegion, unsigned cPages, PGMMSHAREDPAGEDESC paPageDesc);
     558GMMR0DECL(int) GMMR0SharedModuleCheckRange(PGVM pGVM, PGMMSHAREDMODULE pModule, unsigned idxRegion, unsigned cPages, PGMMSHAREDPAGEDESC paPageDesc);
    514559
    515560/**
     
    562607GMMR3DECL(int)  GMMR3BalloonedPages(PVM pVM, GMMBALLOONACTION enmAction, uint32_t cBalloonedPages);
    563608GMMR3DECL(int)  GMMR3RegisterSharedModule(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq);
    564 GMMR3DECL(int)  GMMR3UnregisterSharedModule(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq);
     609GMMR3DECL(int)  GMMR3UnregisterSharedModule(PVM pVM, PGMMUNREGISTERSHAREDMODULEREQ pReq);
     610GMMR3DECL(int)  GMMR3CheckSharedModules(PVM pVM);
    565611GMMR3DECL(int)  GMMR3ResetSharedModules(PVM pVM);
    566612/** @} */
  • trunk/include/VBox/pgm.h

    r29307 r29424  
    433433VMMR0DECL(int)      PGMR0PhysAllocateHandyPages(PVM pVM, PVMCPU pVCpu);
    434434VMMR0DECL(int)      PGMR0PhysAllocateLargeHandyPage(PVM pVM, PVMCPU pVCpu);
    435 VMMR0DECL(int)      PGMR0SharedModuleCheck(PVM pVM, PVMCPU pVCpu, PGMMREGISTERSHAREDMODULEREQ pReq);
     435VMMR0DECL(int)      PGMR0SharedModuleCheckRegion(PVM pVM, VMCPUID idCpu, PGMMSHAREDMODULE pModule, PGVM pGVM);
    436436VMMR0DECL(int)      PGMR0Trap0eHandlerNestedPaging(PVM pVM, PVMCPU pVCpu, PGMMODE enmShwPagingMode, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPHYS pvFault);
    437437# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
     
    569569VMMR3DECL(int)     PGMR3SharedModuleRegister(PVM pVM, VBOXOSFAMILY enmGuestOS, char *pszModuleName, char *pszVersion, RTGCPTR GCBaseAddr, uint32_t cbModule, unsigned cRegions, VMMDEVSHAREDREGIONDESC *pRegions);
    570570VMMR3DECL(int)     PGMR3SharedModuleUnregister(PVM pVM, char *pszModuleName, char *pszVersion, RTGCPTR GCBaseAddr, uint32_t cbModule);
     571VMMR3DECL(int)     PGMR3SharedModuleCheckAll(PVM pVM);
    571572/** @} */
    572573
  • trunk/include/VBox/vmm.h

    r29201 r29424  
    285285    /** Call PGMR0AllocateLargePage(). */
    286286    VMMR0_DO_PGM_ALLOCATE_LARGE_HANDY_PAGE,
    287     /** Call PGMR0CheckSharedModule(). */
    288     VMMR0_DO_PGM_CHECK_SHARED_MODULE,
    289287
    290288    /** Call GMMR0InitialReservation(). */
     
    314312    /** Call GMMR0ResetSharedModules. */
    315313    VMMR0_DO_GMM_RESET_SHARED_MODULES,
     314    /** Call GMMR0CheckSharedModules. */
     315    VMMR0_DO_GMM_CHECK_SHARED_MODULES,
    316316
    317317    /** Set a GVMM or GMM configuration value. */
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServicePageSharing.cpp

    r29420 r29424  
    299299    /* Delete leftover modules in the old tree. */
    300300    RTAvlPVDestroy(&pKnownModuleTree, VBoxServicePageSharingEmptyTreeCallback, NULL);
     301
     302    /* Check all registered modules. */
     303    VbglR3CheckSharedModules();
    301304
    302305    /* Activate new module tree. */
  • trunk/src/VBox/VMM/GMM.cpp

    r29401 r29424  
    391391 * @see GMMR0RegisterSharedModule
    392392 */
    393 GMMR3DECL(int) GMMR3UnregisterSharedModule(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq)
     393GMMR3DECL(int) GMMR3UnregisterSharedModule(PVM pVM, PGMMUNREGISTERSHAREDMODULEREQ pReq)
    394394{
    395395    pReq->Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     
    405405    return VMMR3CallR0(pVM, VMMR0_DO_GMM_RESET_SHARED_MODULES, 0, NULL);
    406406}
     407
     408/**
     409 * @see GMMR0CheckSharedModules
     410 */
     411GMMR3DECL(int)  GMMR3CheckSharedModules(PVM pVM)
     412{
     413    return VMMR3CallR0(pVM, VMMR0_DO_GMM_CHECK_SHARED_MODULES, 0, NULL);
     414}
  • trunk/src/VBox/VMM/PGMSharedPage.cpp

    r29411 r29424  
    3535#include <iprt/mem.h>
    3636
    37 
    38 #ifdef VBOX_WITH_PAGE_SHARING
    39 /**
    40  * Rendezvous callback that will be called once.
    41  *
    42  * @returns VBox strict status code.
    43  * @param   pVM                 VM handle.
    44  * @param   pVCpu               The VMCPU handle for the calling EMT.
    45  * @param   pvUser              PGMMREGISTERSHAREDMODULEREQ
    46  */
    47 static DECLCALLBACK(VBOXSTRICTRC) pgmR3SharedModuleRegRendezvous(PVM pVM, PVMCPU pVCpu, void *pvUser)
    48 {
    49     PGMMREGISTERSHAREDMODULEREQ pReq = (PGMMREGISTERSHAREDMODULEREQ)pvUser;
    50 
    51     return VMMR3CallR0(pVM, VMMR0_DO_PGM_CHECK_SHARED_MODULE, 0, &pReq->Hdr);
    52 }
    53 
    54 /**
    55  * Shared module registration helper (called on the way out).
    56  *
    57  * @param   pVM         The VM handle.
    58  * @param   pReq        Registration request info
    59  */
    60 static DECLCALLBACK(void) pgmR3SharedModuleRegisterHelper(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq)
    61 {
    62     int rc;
    63    
    64     rc = GMMR3RegisterSharedModule(pVM, pReq);
    65     Assert(rc == VINF_SUCCESS || rc == VINF_PGM_SHARED_MODULE_COLLISION || rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED);
    66     if (rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED)
    67     {
    68         PVMCPU   pVCpu = VMMGetCpu(pVM);
    69         unsigned cFlushedPages = 0;
    70 
    71         /** todo count copy-on-write actions in the trap handler so we don't have to check everything all the time! */
    72 
    73         /* Count the number of shared pages that were changed (copy-on-write). */
    74         for (unsigned i = 0; i < pReq->cRegions; i++)
    75         {
    76             Assert((pReq->aRegions[i].cbRegion & 0xfff) == 0);
    77             Assert((pReq->aRegions[i].GCRegionAddr & 0xfff) == 0);
    78 
    79             RTGCPTR GCRegion  = pReq->aRegions[i].GCRegionAddr;
    80             uint32_t cbRegion = pReq->aRegions[i].cbRegion & ~0xfff;
    81 
    82             while (cbRegion)
    83             {
    84                 RTGCPHYS GCPhys;
    85                 uint64_t fFlags;
    86 
    87                 rc = PGMGstGetPage(pVCpu, GCRegion, &fFlags, &GCPhys);
    88                 if (    rc == VINF_SUCCESS
    89                     &&  !(fFlags & X86_PTE_RW))
    90                 {
    91                     PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
    92                     if (    pPage
    93                         &&  !PGM_PAGE_IS_SHARED(pPage))
    94                     {
    95                         cFlushedPages++;
    96                     }
    97                 }
    98 
    99                 GCRegion += PAGE_SIZE;
    100                 cbRegion -= PAGE_SIZE;
    101             }
    102         }
    103 
    104         if (cFlushedPages > 32)
    105             rc = VINF_SUCCESS;  /* force recheck below */
    106     }
    107     /* Full (re)check needed? */
    108     if (rc == VINF_SUCCESS)
    109     {
    110         pReq->Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
    111         pReq->Hdr.cbReq = RT_OFFSETOF(GMMREGISTERSHAREDMODULEREQ, aRegions[pReq->cRegions]);
    112 
    113         /* We must stall other VCPUs as we'd otherwise have to send IPI flush commands for every single change we make. */
    114         rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, pgmR3SharedModuleRegRendezvous, pReq);
    115         AssertRC(rc);
    116     }
    117     RTMemFree(pReq);
    118     return;
    119 }
    120 #endif
    12137
    12238/**
     
    16177    }
    16278
    163     /* Queue the actual registration as we are under the IOM lock right now. Perform this operation on the way out. */
    164     return VMR3ReqCallNoWait(pVM, VMMGetCpuId(pVM), (PFNRT)pgmR3SharedModuleRegisterHelper, 2, pVM, pReq);
     79    int rc = GMMR3RegisterSharedModule(pVM, pReq);
     80    RTMemFree(pReq);
     81    Assert(rc == VINF_SUCCESS || rc == VINF_PGM_SHARED_MODULE_COLLISION || rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED);
     82    if (RT_FAILURE(rc))
     83        return rc;
     84    return VINF_SUCCESS;
    16585#else
    16686    return VERR_NOT_IMPLEMENTED;
    16787#endif
    16888}
    169 
    170 
    171 #ifdef VBOX_WITH_PAGE_SHARING
    172 /**
    173  * Shared module unregistration helper (called on the way out).
    174  *
    175  * @param   pVM         The VM handle.
    176  * @param   pReq        Unregistration request info
    177  */
    178 static DECLCALLBACK(void) pgmR3SharedModuleUnregisterHelper(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq)
    179 {
    180     int rc;
    181    
    182     rc = GMMR3UnregisterSharedModule(pVM, pReq);
    183     RTMemFree(pReq);
    184     return;
    185 }
    186 #endif
    18789
    18890/**
     
    212114        ||  RTStrCopy(pReq->szVersion, sizeof(pReq->szVersion), pszVersion) != VINF_SUCCESS)
    213115    {
     116        RTMemFree(pReq);
    214117        return VERR_BUFFER_OVERFLOW;
    215118    }
    216     /* Queue the actual registration as we are under the IOM lock right now. Perform this operation on the way out. */
    217     return VMR3ReqCallNoWait(pVM, VMMGetCpuId(pVM), (PFNRT)pgmR3SharedModuleUnregisterHelper, 2, pVM, pReq);
     119    int rc = GMMR3UnregisterSharedModule(pVM, pReq);
     120    RTMemFree(pReq);
     121    return rc;
    218122#else
    219123    return VERR_NOT_IMPLEMENTED;
    220124#endif
    221125}
     126
     127#ifdef VBOX_WITH_PAGE_SHARING
     128/**
     129 * Rendezvous callback that will be called once.
     130 *
     131 * @returns VBox strict status code.
     132 * @param   pVM                 VM handle.
     133 * @param   pVCpu               The VMCPU handle for the calling EMT.
     134 * @param   pvUser              Not used;
     135 */
     136static DECLCALLBACK(VBOXSTRICTRC) pgmR3SharedModuleRegRendezvous(PVM pVM, PVMCPU pVCpu, void *pvUser)
     137{
     138    return GMMR3CheckSharedModules(pVM);
     139}
     140
     141/**
     142 * Shared module unregistration helper (called on the way out).
     143 *
     144 * @param   pVM         The VM handle.
     145 */
     146static DECLCALLBACK(void) pgmR3CheckSharedModulesHelper(PVM pVM)
     147{   
     148    /* We must stall other VCPUs as we'd otherwise have to send IPI flush commands for every single change we make. */
     149    int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, pgmR3SharedModuleRegRendezvous, NULL);
     150    AssertRC(rc);
     151}
     152#endif
     153
     154/**
     155 * Check all registered modules for changes.
     156 *
     157 * @returns VBox status code.
     158 * @param   pVM                 VM handle
     159 */
     160VMMR3DECL(int) PGMR3SharedModuleCheckAll(PVM pVM)
     161{
     162#ifdef VBOX_WITH_PAGE_SHARING
     163    /* Queue the actual registration as we are under the IOM lock right now. Perform this operation on the way out. */
     164    return VMR3ReqCallNoWait(pVM, VMMGetCpuId(pVM), (PFNRT)pgmR3CheckSharedModulesHelper, 1, pVM);
     165#else
     166    return VERR_NOT_IMPLEMENTED;
     167#endif
     168}
  • trunk/src/VBox/VMM/VMMR0/GMMR0.cpp

    r29417 r29424  
    154154#include "GMMR0Internal.h"
    155155#include <VBox/gvm.h>
     156#include <VBox/pgm.h>
    156157#include <VBox/log.h>
    157158#include <VBox/param.h>
     
    37183719 *
    37193720 * @returns VBox status code.
    3720  * @param   pVM                 VM handle
    3721  * @param   idCpu               VCPU id
    3722  * @param   pReq                Module description
     3721 * @param   pGMM                Pointer to the GMM instance data.
     3722 * @param   pGVM                Pointer to the GVM instance data.
     3723 * @param   pModule             Module description
    37233724 * @param   idxRegion           Region index
    37243725 * @param   cPages              Number of entries in the paPageDesc array
    37253726 * @param   paPageDesc          Page descriptor array (in/out)
    37263727 */
    3727 GMMR0DECL(int) GMMR0SharedModuleCheckRange(PVM pVM, VMCPUID idCpu, PGMMREGISTERSHAREDMODULEREQ pReq, unsigned idxRegion, unsigned cPages, PGMMSHAREDPAGEDESC paPageDesc)
    3728 {
    3729     AssertReturn(idxRegion < pReq->cRegions, VERR_INVALID_PARAMETER);
    3730     AssertReturn(cPages == (pReq->aRegions[idxRegion].cbRegion >> PAGE_SHIFT), VERR_INVALID_PARAMETER);
    3731 
    3732     Log(("GMMR0SharedModuleCheckRange %s base %RGv region %d cPages %d\n", pReq->szName, pReq->GCBaseAddr, idxRegion, cPages));
    3733 
     3728GMMR0DECL(int) GMMR0SharedModuleCheckRange(PGVM pGVM, PGMMSHAREDMODULE pModule, unsigned idxRegion, unsigned cPages, PGMMSHAREDPAGEDESC paPageDesc)
     3729{
     3730    int rc = VINF_SUCCESS;
     3731    PGMM pGMM;
     3732    GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR);
     3733
     3734    AssertReturn(idxRegion < pModule->cRegions, VERR_INVALID_PARAMETER);
     3735    AssertReturn(cPages == (pModule->aRegions[idxRegion].cbRegion >> PAGE_SHIFT), VERR_INVALID_PARAMETER);
     3736
     3737    Log(("GMMR0SharedModuleCheckRange %s base %RGv region %d cPages %d\n", pModule->szName, pModule->Core.Key, idxRegion, cPages));
     3738
     3739    PGMMSHAREDREGIONDESC pGlobalRegion = &pModule->aRegions[idxRegion];
     3740
     3741    if (!pGlobalRegion->paHCPhysPageID)
     3742    {
     3743        /* First time; create a page descriptor array. */
     3744        Log(("Allocate page descriptor array for %d pages\n", cPages));
     3745        pGlobalRegion->paHCPhysPageID = (uint32_t *)RTMemAlloc(cPages * sizeof(*pGlobalRegion->paHCPhysPageID));
     3746        if (!pGlobalRegion->paHCPhysPageID)
     3747        {
     3748            AssertFailed();
     3749            rc = VERR_NO_MEMORY;
     3750            goto end;
     3751        }
     3752        /* Invalidate all descriptors. */
     3753        for (unsigned i = 0; i < cPages; i++)
     3754            pGlobalRegion->paHCPhysPageID[i] = NIL_GMM_PAGEID;
     3755    }
     3756
     3757    /* Check all pages in the region. */
     3758    for (unsigned i = 0; i < cPages; i++)
     3759    {
     3760        /* Valid page present? */
     3761        if (paPageDesc[i].uHCPhysPageId != NIL_GMM_PAGEID)
     3762        {
     3763            /* We've seen this shared page for the first time? */
     3764            if (pGlobalRegion->paHCPhysPageID[i] == NIL_GMM_PAGEID)
     3765            {
     3766                /* Easy case: just change the internal page type. */
     3767                PGMMPAGE pPage = gmmR0GetPage(pGMM, paPageDesc[i].uHCPhysPageId);
     3768                if (!pPage)
     3769                {
     3770                    AssertFailed();
     3771                    rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
     3772                    goto end;
     3773                }
     3774                Log(("New shared page guest %RGp host %RHp\n", paPageDesc[i].GCPhys, paPageDesc[i].HCPhys));
     3775
     3776                AssertMsg(paPageDesc[i].GCPhys == (pPage->Private.pfn << 12), ("desc %RGp gmm %RGp\n", paPageDesc[i].HCPhys, (pPage->Private.pfn << 12)));
     3777
     3778                gmmR0ConvertToSharedPage(pGMM, pGVM, paPageDesc[i].HCPhys, paPageDesc[i].uHCPhysPageId, pPage);
     3779
     3780                /* Keep track of these references. */
     3781                pGlobalRegion->paHCPhysPageID[i] = paPageDesc[i].uHCPhysPageId;
     3782            }
     3783            else
     3784            {
     3785                uint8_t  *pbLocalPage, *pbSharedPage;
     3786                uint8_t  *pbChunk;
     3787                PGMMCHUNK pChunk;
     3788
     3789                Assert(paPageDesc[i].uHCPhysPageId != pGlobalRegion->paHCPhysPageID[i]);
     3790
     3791                /* Get the shared page source. */
     3792                PGMMPAGE pPage = gmmR0GetPage(pGMM, pGlobalRegion->paHCPhysPageID[i]);
     3793                if (!pPage)
     3794                {
     3795                    AssertFailed();
     3796                    rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
     3797                    goto end;
     3798                }
     3799                Assert(pPage->Common.u2State == GMM_PAGE_STATE_SHARED);
     3800
     3801                Log(("Replace existing page guest %RGp host %RHp -> %RHp\n", paPageDesc[i].GCPhys, paPageDesc[i].HCPhys, pPage->Shared.pfn << PAGE_SHIFT));
     3802
     3803                /* Calculate the virtual address of the local page. */
     3804                pChunk = gmmR0GetChunk(pGMM, paPageDesc[i].uHCPhysPageId >> GMM_CHUNKID_SHIFT);
     3805                if (pChunk)
     3806                {
     3807                    if (!gmmR0IsChunkMapped(pGVM, pChunk, (PRTR3PTR)&pbChunk))
     3808                    {
     3809                        AssertFailed();
     3810                        rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
     3811                        goto end;
     3812                    }
     3813                    pbLocalPage = pbChunk + ((paPageDesc[i].uHCPhysPageId & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
     3814                }
     3815                else
     3816                {
     3817                    AssertFailed();
     3818                    rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
     3819                    goto end;
     3820                }
     3821
     3822                /* Calculate the virtual address of the shared page. */
     3823                pChunk = gmmR0GetChunk(pGMM, pGlobalRegion->paHCPhysPageID[i] >> GMM_CHUNKID_SHIFT);
     3824                Assert(pChunk); /* can't fail as gmmR0GetPage succeeded. */
     3825
     3826                /* Get the virtual address of the physical page; map the chunk into the VM process if not already done. */
     3827                if (!gmmR0IsChunkMapped(pGVM, pChunk, (PRTR3PTR)&pbChunk))
     3828                {
     3829                    rc = gmmR0MapChunk(pGMM, pGVM, pChunk, (PRTR3PTR)&pbChunk);
     3830                    if (rc != VINF_SUCCESS)
     3831                    {
     3832                        AssertRC(rc);
     3833                        goto end;
     3834                    }
     3835                }
     3836                pbSharedPage = pbChunk + ((pGlobalRegion->paHCPhysPageID[i] & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
     3837
     3838                /** todo write ASMMemComparePage. */
     3839                if (memcmp(pbSharedPage, pbLocalPage, PAGE_SIZE))
     3840                {
     3841                    Log(("Unexpected differences found between local and shared page; skip\n"));
     3842                    /* Signal to the caller that this one hasn't changed. */
     3843                    paPageDesc[i].uHCPhysPageId = NIL_GMM_PAGEID;
     3844                    continue;
     3845                }
     3846
     3847                /* Free the old local page. */
     3848                GMMFREEPAGEDESC PageDesc;
     3849
     3850                PageDesc.idPage = paPageDesc[i].uHCPhysPageId;
     3851                rc = gmmR0FreePages(pGMM, pGVM, 1, &PageDesc, GMMACCOUNT_BASE);
     3852                AssertRC(rc);
     3853
     3854                gmmR0UseSharedPage(pGMM, pGVM, pPage);
     3855
     3856                /* Pass along the new physical address & page id. */
     3857                paPageDesc[i].HCPhys        = pPage->Shared.pfn << PAGE_SHIFT;
     3858                paPageDesc[i].uHCPhysPageId = pGlobalRegion->paHCPhysPageID[i];
     3859            }
     3860        }
     3861    }
     3862end:
     3863    return rc;
     3864}
     3865
     3866/**
     3867 * RTAvlU32Destroy callback.
     3868 *
     3869 * @returns 0
     3870 * @param   pNode   The node to destroy.
     3871 * @param   pvGVM   The GVM handle.
     3872 */
     3873static DECLCALLBACK(int) gmmR0CleanupSharedModule(PAVLGCPTRNODECORE pNode, void *pvGVM)
     3874{
     3875    PGVM pGVM = (PGVM)pvGVM;
     3876    PGMMSHAREDMODULEPERVM pRecVM = (PGMMSHAREDMODULEPERVM)pNode;
     3877
     3878    Assert(pRecVM->pGlobalModule);
     3879    if (pRecVM->pGlobalModule)
     3880    {
     3881        PGMMSHAREDMODULE pRec = pRecVM->pGlobalModule;
     3882        Assert(pRec);
     3883        Assert(pRec->cUsers);
     3884
     3885        pRec->cUsers--;
     3886        if (pRec->cUsers == 0)
     3887        {
     3888            for (unsigned i = 0; i < pRec->cRegions; i++)
     3889                if (pRec->aRegions[i].paHCPhysPageID)
     3890                    RTMemFree(pRec->aRegions[i].paHCPhysPageID);
     3891
     3892            RTMemFree(pRec);
     3893        }
     3894    }
     3895    RTMemFree(pRecVM);
     3896    return 0;
     3897}
     3898#endif
     3899
     3900/**
     3901 * Removes all shared modules for the specified VM
     3902 *
     3903 * @returns VBox status code.
     3904 * @param   pVM                 VM handle
     3905 * @param   idCpu               VCPU id
     3906 */
     3907GMMR0DECL(int) GMMR0ResetSharedModules(PVM pVM, VMCPUID idCpu)
     3908{
     3909#ifdef VBOX_WITH_PAGE_SHARING
    37343910    /*
    37353911     * Validate input and get the basics.
     
    37493925    if (GMM_CHECK_SANITY_UPON_ENTERING(pGMM))
    37503926    {
    3751         PGMMSHAREDMODULEPERVM pLocalModule = (PGMMSHAREDMODULEPERVM)RTAvlGCPtrGet(&pGVM->gmm.s.pSharedModuleTree, pReq->GCBaseAddr);
    3752         if (    !pLocalModule
    3753             ||  pLocalModule->fCollision)
    3754         {
    3755             Assert(!pLocalModule);
    3756             rc = VERR_PGM_SHARED_MODULE_NOT_FOUND;
    3757             goto end;
    3758         }
    3759 
    3760         PGMMSHAREDMODULE     pGlobalModule = pLocalModule->pGlobalModule;
    3761         PGMMSHAREDREGIONDESC pGlobalRegion = &pGlobalModule->aRegions[idxRegion];
    3762 
    3763         if (!pGlobalRegion->paHCPhysPageID)
    3764         {
    3765             /* First time; create a page descriptor array. */
    3766             Log(("Allocate page descriptor array for %d pages\n", cPages));
    3767             pGlobalRegion->paHCPhysPageID = (uint32_t *)RTMemAlloc(cPages * sizeof(*pGlobalRegion->paHCPhysPageID));
    3768             if (!pGlobalRegion->paHCPhysPageID)
    3769             {
    3770                 AssertFailed();
    3771                 rc = VERR_NO_MEMORY;
    3772                 goto end;
    3773             }
    3774             /* Invalidate all descriptors. */
    3775             for (unsigned i = 0; i < cPages; i++)
    3776                 pGlobalRegion->paHCPhysPageID[i] = NIL_GMM_PAGEID;
    3777         }
    3778 
    3779         /* Check all pages in the region. */
    3780         for (unsigned i = 0; i < cPages; i++)
    3781         {
    3782             /* Valid page present? */
    3783             if (paPageDesc[i].uHCPhysPageId != NIL_GMM_PAGEID)
    3784             {
    3785                 /* We've seen this shared page for the first time? */
    3786                 if (pGlobalRegion->paHCPhysPageID[i] == NIL_GMM_PAGEID)
    3787                 {
    3788                     /* Easy case: just change the internal page type. */
    3789                     PGMMPAGE pPage = gmmR0GetPage(pGMM, paPageDesc[i].uHCPhysPageId);
    3790                     if (!pPage)
    3791                     {
    3792                         AssertFailed();
    3793                         rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    3794                         goto end;
    3795                     }
    3796                     Log(("New shared page guest %RGp host %RHp\n", paPageDesc[i].GCPhys, paPageDesc[i].HCPhys));
    3797 
    3798                     AssertMsg(paPageDesc[i].GCPhys == (pPage->Private.pfn << 12), ("desc %RGp gmm %RGp\n", paPageDesc[i].HCPhys, (pPage->Private.pfn << 12)));
    3799 
    3800                     gmmR0ConvertToSharedPage(pGMM, pGVM, paPageDesc[i].HCPhys, paPageDesc[i].uHCPhysPageId, pPage);
    3801 
    3802                     /* Keep track of these references. */
    3803                     pGlobalRegion->paHCPhysPageID[i] = paPageDesc[i].uHCPhysPageId;
    3804                 }
    3805                 else
    3806                 {
    3807                     uint8_t  *pbLocalPage, *pbSharedPage;
    3808                     uint8_t  *pbChunk;
    3809                     PGMMCHUNK pChunk;
    3810 
    3811                     Assert(paPageDesc[i].uHCPhysPageId != pGlobalRegion->paHCPhysPageID[i]);
    3812 
    3813                     /* Get the shared page source. */
    3814                     PGMMPAGE pPage = gmmR0GetPage(pGMM, pGlobalRegion->paHCPhysPageID[i]);
    3815                     if (!pPage)
    3816                     {
    3817                         AssertFailed();
    3818                         rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    3819                         goto end;
    3820                     }
    3821                     Assert(pPage->Common.u2State == GMM_PAGE_STATE_SHARED);
    3822 
    3823                     Log(("Replace existing page guest %RGp host %RHp -> %RHp\n", paPageDesc[i].GCPhys, paPageDesc[i].HCPhys, pPage->Shared.pfn << PAGE_SHIFT));
    3824 
    3825                     /* Calculate the virtual address of the local page. */
    3826                     pChunk = gmmR0GetChunk(pGMM, paPageDesc[i].uHCPhysPageId >> GMM_CHUNKID_SHIFT);
    3827                     if (pChunk)
    3828                     {
    3829                         if (!gmmR0IsChunkMapped(pGVM, pChunk, (PRTR3PTR)&pbChunk))
    3830                         {
    3831                             AssertFailed();
    3832                             rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    3833                             goto end;
    3834                         }
    3835                         pbLocalPage = pbChunk + ((paPageDesc[i].uHCPhysPageId & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
    3836                     }
    3837                     else
    3838                     {
    3839                         AssertFailed();
    3840                         rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    3841                         goto end;
    3842                     }
    3843 
    3844                     /* Calculate the virtual address of the shared page. */
    3845                     pChunk = gmmR0GetChunk(pGMM, pGlobalRegion->paHCPhysPageID[i] >> GMM_CHUNKID_SHIFT);
    3846                     Assert(pChunk); /* can't fail as gmmR0GetPage succeeded. */
    3847 
    3848                     /* Get the virtual address of the physical page; map the chunk into the VM process if not already done. */
    3849                     if (!gmmR0IsChunkMapped(pGVM, pChunk, (PRTR3PTR)&pbChunk))
    3850                     {
    3851                         rc = gmmR0MapChunk(pGMM, pGVM, pChunk, (PRTR3PTR)&pbChunk);
    3852                         if (rc != VINF_SUCCESS)
    3853                         {
    3854                             AssertRC(rc);
    3855                             goto end;
    3856                         }
    3857                     }
    3858                     pbSharedPage = pbChunk + ((pGlobalRegion->paHCPhysPageID[i] & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
    3859 
    3860                     /** todo write ASMMemComparePage. */
    3861                     if (memcmp(pbSharedPage, pbLocalPage, PAGE_SIZE))
    3862                     {
    3863                         Log(("Unexpected differences found between local and shared page; skip\n"));
    3864                         /* Signal to the caller that this one hasn't changed. */
    3865                         paPageDesc[i].uHCPhysPageId = NIL_GMM_PAGEID;
    3866                         continue;
    3867                     }
    3868 
    3869                     /* Free the old local page. */
    3870                     GMMFREEPAGEDESC PageDesc;
    3871 
    3872                     PageDesc.idPage = paPageDesc[i].uHCPhysPageId;
    3873                     rc = gmmR0FreePages(pGMM, pGVM, 1, &PageDesc, GMMACCOUNT_BASE);
    3874                     AssertRC(rc);
    3875 
    3876                     gmmR0UseSharedPage(pGMM, pGVM, pPage);
    3877 
    3878                     /* Pass along the new physical address & page id. */
    3879                     paPageDesc[i].HCPhys        = pPage->Shared.pfn << PAGE_SHIFT;
    3880                     paPageDesc[i].uHCPhysPageId = pGlobalRegion->paHCPhysPageID[i];
    3881                 }
    3882             }
    3883         }
    3884 
     3927        RTAvlGCPtrDestroy(&pGVM->gmm.s.pSharedModuleTree, gmmR0CleanupSharedModule, pGVM);
     3928
     3929        rc = VINF_SUCCESS;
    38853930        GMM_CHECK_SANITY_UPON_LEAVING(pGMM);
    38863931    }
     
    38883933        rc = VERR_INTERNAL_ERROR_5;
    38893934
    3890 end:
    38913935    RTSemFastMutexRelease(pGMM->Mtx);
    38923936    return rc;
    3893 }
    3894 
    3895 /**
    3896  * RTAvlU32Destroy callback.
    3897  *
    3898  * @returns 0
    3899  * @param   pNode   The node to destroy.
    3900  * @param   pvGVM   The GVM handle.
    3901  */
    3902 static DECLCALLBACK(int) gmmR0CleanupSharedModule(PAVLGCPTRNODECORE pNode, void *pvGVM)
    3903 {
    3904     PGVM pGVM = (PGVM)pvGVM;
    3905     PGMMSHAREDMODULEPERVM pRecVM = (PGMMSHAREDMODULEPERVM)pNode;
    3906 
    3907     Assert(pRecVM->pGlobalModule);
    3908     if (pRecVM->pGlobalModule)
    3909     {
    3910         PGMMSHAREDMODULE pRec = pRecVM->pGlobalModule;
    3911         Assert(pRec);
    3912         Assert(pRec->cUsers);
    3913 
    3914         pRec->cUsers--;
    3915         if (pRec->cUsers == 0)
    3916         {
    3917             for (unsigned i = 0; i < pRec->cRegions; i++)
    3918                 if (pRec->aRegions[i].paHCPhysPageID)
    3919                     RTMemFree(pRec->aRegions[i].paHCPhysPageID);
    3920 
    3921             RTMemFree(pRec);
    3922         }
    3923     }
    3924     RTMemFree(pRecVM);
     3937#else
     3938    return VERR_NOT_IMPLEMENTED;
     3939#endif
     3940}
     3941
     3942#ifdef VBOX_WITH_PAGE_SHARING
     3943typedef struct
     3944{
     3945    PGVM    pGVM;
     3946    VMCPUID idCpu;
     3947} GMMCHECKSHAREDMODULEINFO, *PGMMCHECKSHAREDMODULEINFO;
     3948
     3949/**
     3950 * Tree enumeration callback for checking a shared module.
     3951 */
     3952DECLCALLBACK(int) gmmR0CheckSharedModule(PAVLGCPTRNODECORE pNode, void *pvUser)
     3953{
     3954    PGMMCHECKSHAREDMODULEINFO   pInfo = (PGMMCHECKSHAREDMODULEINFO)pvUser;
     3955    PGMMSHAREDMODULEPERVM       pLocalModule = (PGMMSHAREDMODULEPERVM)pNode;
     3956    PGMMSHAREDMODULE            pGlobalModule = pLocalModule->pGlobalModule;
     3957
     3958    Log(("gmmR0CheckSharedModule: check %s %s base=%RGv size=%x collision=%d\n", pGlobalModule->szName, pGlobalModule->szVersion, pGlobalModule->Core.Key, pGlobalModule->cbModule, pLocalModule->fCollision));
     3959    if (!pLocalModule->fCollision)
     3960    {
     3961        PGMR0SharedModuleCheckRegion(pInfo->pGVM->pVM, pInfo->idCpu, pGlobalModule, pInfo->pGVM);
     3962    }
    39253963    return 0;
    39263964}
     
    39283966
    39293967/**
    3930  * Removes all shared modules for the specified VM
     3968 * Check all shared modules for the specified VM
    39313969 *
    39323970 * @returns VBox status code.
     
    39343972 * @param   idCpu               VCPU id
    39353973 */
    3936 GMMR0DECL(int) GMMR0ResetSharedModules(PVM pVM, VMCPUID idCpu)
     3974GMMR0DECL(int) GMMR0CheckSharedModules(PVM pVM, VMCPUID idCpu)
    39373975{
    39383976#ifdef VBOX_WITH_PAGE_SHARING
     
    39543992    if (GMM_CHECK_SANITY_UPON_ENTERING(pGMM))
    39553993    {
    3956         RTAvlGCPtrDestroy(&pGVM->gmm.s.pSharedModuleTree, gmmR0CleanupSharedModule, pGVM);
     3994        GMMCHECKSHAREDMODULEINFO Info;
     3995
     3996        Info.pGVM = pGVM;
     3997        Info.idCpu = idCpu;
     3998
     3999        RTAvlGCPtrDoWithAll(&pGVM->gmm.s.pSharedModuleTree, true /* fFromLeft */, gmmR0CheckSharedModule, &Info);
    39574000
    39584001        rc = VINF_SUCCESS;
  • trunk/src/VBox/VMM/VMMR0/GMMR0Internal.h

    r29308 r29424  
    3737/** Pointer to a GMMVMSIZES. */
    3838typedef GMMVMSIZES *PGMMVMSIZES;
    39 
    40 /**
    41  * Shared region descriptor
    42  */
    43 typedef struct GMMSHAREDREGIONDESC
    44 {
    45     /** Region base address. */
    46     RTGCPTR64           GCRegionAddr;
    47     /** Region size. */
    48     uint32_t            cbRegion;
    49     /** Alignment. */
    50     uint32_t            u32Alignment;
    51     /** Pointer to physical page id array. */
    52     uint32_t           *paHCPhysPageID;
    53 } GMMSHAREDREGIONDESC;
    54 /** Pointer to a GMMSHAREDREGIONDESC. */
    55 typedef GMMSHAREDREGIONDESC *PGMMSHAREDREGIONDESC;
    56 
    57 
    58 /**
    59  * Shared module registration info (global)
    60  */
    61 typedef struct GMMSHAREDMODULE
    62 {
    63     /* Tree node. */
    64     AVLGCPTRNODECORE            Core;
    65     /** Shared module size. */
    66     uint32_t                    cbModule;
    67     /** Number of included region descriptors */
    68     uint32_t                    cRegions;
    69     /** Number of users (VMs). */
    70     uint32_t                    cUsers;
    71     /** Guest OS family type. */
    72     VBOXOSFAMILY                enmGuestOS;
    73     /** Module name */
    74     char                        szName[GMM_SHARED_MODULE_MAX_NAME_STRING];
    75     /** Module version */
    76     char                        szVersion[GMM_SHARED_MODULE_MAX_VERSION_STRING];
    77     /** Shared region descriptor(s). */
    78     GMMSHAREDREGIONDESC         aRegions[1];
    79 } GMMSHAREDMODULE;
    80 /** Pointer to a GMMSHAREDMODULE. */
    81 typedef GMMSHAREDMODULE *PGMMSHAREDMODULE;
    8239
    8340/**
  • trunk/src/VBox/VMM/VMMR0/PGMR0.cpp

    r29418 r29424  
    2121#define LOG_GROUP LOG_GROUP_PGM
    2222#include <VBox/pgm.h>
     23#include <VBox/gmm.h>
    2324#include "../PGMInternal.h"
    2425#include <VBox/vm.h>
     
    308309 *
    309310 * @param   pVM         The VM handle.
    310  * @param   pVCpu       The VMCPU handle.
    311  * @param   pReq        Module request packet
    312  */
    313 VMMR0DECL(int) PGMR0SharedModuleCheck(PVM pVM, PVMCPU pVCpu, PGMMREGISTERSHAREDMODULEREQ pReq)
     311 * @param   idCpu       VCPU id
     312 * @param   pModule     Module description
     313 * @param   pGVM        Pointer to the GVM instance data.
     314 */
     315VMMR0DECL(int) PGMR0SharedModuleCheckRegion(PVM pVM, VMCPUID idCpu, PGMMSHAREDMODULE pModule, PGVM pGVM)
    314316{
    315317    int                rc = VINF_SUCCESS;
     
    317319    uint32_t           cbPreviousRegion  = 0;
    318320    bool               fFlushTLBs = false;
    319 
    320     /*
    321      * Validate input.
    322      */
    323     AssertPtrReturn(pReq, VERR_INVALID_POINTER);
    324     AssertMsgReturn(pReq->Hdr.cbReq >= sizeof(*pReq) && pReq->Hdr.cbReq == RT_UOFFSETOF(GMMREGISTERSHAREDMODULEREQ, aRegions[pReq->cRegions]), ("%#x != %#x\n", pReq->Hdr.cbReq, RT_UOFFSETOF(GMMREGISTERSHAREDMODULEREQ, aRegions[pReq->cRegions])), VERR_INVALID_PARAMETER);
    325 
    326     Log(("PGMR0SharedModuleCheck: check %s %s base=%RGv size=%x\n", pReq->szName, pReq->szVersion, pReq->GCBaseAddr, pReq->cbModule));
     321    PVMCPU             pVCpu = &pVM->aCpus[idCpu];
     322
     323    Log(("PGMR0SharedModuleCheck: check %s %s base=%RGv size=%x\n", pModule->szName, pModule->szVersion, pModule->Core.Key, pModule->cbModule));
    327324
    328325    pgmLock(pVM);
    329326
    330327    /* Check every region of the shared module. */
    331     for (unsigned i = 0; i < pReq->cRegions; i++)
    332     {
    333         Assert((pReq->aRegions[i].cbRegion & 0xfff) == 0);
    334         Assert((pReq->aRegions[i].GCRegionAddr & 0xfff) == 0);
    335 
    336         RTGCPTR  GCRegion  = pReq->aRegions[i].GCRegionAddr;
    337         unsigned cbRegion = pReq->aRegions[i].cbRegion & ~0xfff;
     328    for (unsigned i = 0; i < pModule->cRegions; i++)
     329    {
     330        Assert((pModule->aRegions[i].cbRegion & 0xfff) == 0);
     331        Assert((pModule->aRegions[i].GCRegionAddr & 0xfff) == 0);
     332
     333        RTGCPTR  GCRegion  = pModule->aRegions[i].GCRegionAddr;
     334        unsigned cbRegion = pModule->aRegions[i].cbRegion & ~0xfff;
    338335        unsigned idxPage = 0;
    339336        bool     fValidChanges = false;
     
    385382        if (fValidChanges)
    386383        {
    387             rc = GMMR0SharedModuleCheckRange(pVM, pVCpu->idCpu, pReq, i, idxPage, paPageDesc);
     384            rc = GMMR0SharedModuleCheckRange(pGVM, pModule, i, idxPage, paPageDesc);
    388385            AssertRC(rc);
    389386            if (RT_FAILURE(rc))
     
    452449}
    453450#endif
     451
     452#if 0
     453/**
     454 * Shared module registration helper (called on the way out).
     455 *
     456 * @param   pVM         The VM handle.
     457 * @param   pReq        Registration request info
     458 */
     459static DECLCALLBACK(void) pgmR3SharedModuleRegisterHelper(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq)
     460{
     461    int rc;
     462   
     463    rc = GMMR3RegisterSharedModule(pVM, pReq);
     464    Assert(rc == VINF_SUCCESS || rc == VINF_PGM_SHARED_MODULE_COLLISION || rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED);
     465    if (rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED)
     466    {
     467        PVMCPU   pVCpu = VMMGetCpu(pVM);
     468        unsigned cFlushedPages = 0;
     469
     470        /** todo count copy-on-write actions in the trap handler so we don't have to check everything all the time! */
     471
     472        /* Count the number of shared pages that were changed (copy-on-write). */
     473        for (unsigned i = 0; i < pReq->cRegions; i++)
     474        {
     475            Assert((pReq->aRegions[i].cbRegion & 0xfff) == 0);
     476            Assert((pReq->aRegions[i].GCRegionAddr & 0xfff) == 0);
     477
     478            RTGCPTR GCRegion  = pReq->aRegions[i].GCRegionAddr;
     479            uint32_t cbRegion = pReq->aRegions[i].cbRegion & ~0xfff;
     480
     481            while (cbRegion)
     482            {
     483                RTGCPHYS GCPhys;
     484                uint64_t fFlags;
     485
     486                rc = PGMGstGetPage(pVCpu, GCRegion, &fFlags, &GCPhys);
     487                if (    rc == VINF_SUCCESS
     488                    &&  !(fFlags & X86_PTE_RW))
     489                {
     490                    PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
     491                    if (    pPage
     492                        &&  !PGM_PAGE_IS_SHARED(pPage))
     493                    {
     494                        cFlushedPages++;
     495                    }
     496                }
     497
     498                GCRegion += PAGE_SIZE;
     499                cbRegion -= PAGE_SIZE;
     500            }
     501        }
     502
     503        if (cFlushedPages > 32)
     504            rc = VINF_SUCCESS;  /* force recheck below */
     505    }
     506    /* Full (re)check needed? */
     507    if (rc == VINF_SUCCESS)
     508    {
     509        pReq->Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     510        pReq->Hdr.cbReq = RT_OFFSETOF(GMMREGISTERSHAREDMODULEREQ, aRegions[pReq->cRegions]);
     511
     512        /* We must stall other VCPUs as we'd otherwise have to send IPI flush commands for every single change we make. */
     513        rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, pgmR3SharedModuleRegRendezvous, pReq);
     514        AssertRC(rc);
     515    }
     516    RTMemFree(pReq);
     517    return;
     518}
     519#endif
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r29250 r29424  
    878878            return PGMR0PhysAllocateLargeHandyPage(pVM, &pVM->aCpus[idCpu]);
    879879
    880 #ifdef VBOX_WITH_PAGE_SHARING
    881         case VMMR0_DO_PGM_CHECK_SHARED_MODULE:
    882         {
    883             if (idCpu == NIL_VMCPUID)
    884                 return VERR_INVALID_CPU_ID;
    885 
    886             PVMCPU pVCpu = &pVM->aCpus[idCpu];
    887 
    888             /* Select a valid VCPU context. */
    889             ASMAtomicWriteU32(&pVCpu->idHostCpu, RTMpCpuId());
    890 
    891             int rc = PGMR0SharedModuleCheck(pVM, pVCpu, (PGMMREGISTERSHAREDMODULEREQ)pReqHdr);
    892 
    893             /* Clear the VCPU context. */
    894             ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID);
    895             return rc;
    896         }
    897 #endif
    898 
    899880        /*
    900881         * GMM wrappers.
     
    973954                return VERR_INVALID_PARAMETER;
    974955            return GMMR0ResetSharedModules(pVM, idCpu);
     956
     957#ifdef VBOX_WITH_PAGE_SHARING
     958        case VMMR0_DO_GMM_CHECK_SHARED_MODULES:
     959        {
     960            if (idCpu == NIL_VMCPUID)
     961                return VERR_INVALID_CPU_ID;
     962            if (    u64Arg
     963                ||  pReqHdr)
     964                return VERR_INVALID_PARAMETER;
     965
     966            PVMCPU pVCpu = &pVM->aCpus[idCpu];
     967
     968            /* Select a valid VCPU context. */
     969            ASMAtomicWriteU32(&pVCpu->idHostCpu, RTMpCpuId());
     970
     971            int rc = GMMR0CheckSharedModules(pVM, idCpu);
     972
     973            /* Clear the VCPU context. */
     974            ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID);
     975            return rc;
     976        }
     977#endif
    975978
    976979        /*
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