VirtualBox

Changeset 29168 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
May 6, 2010 4:01:48 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
61241
Message:

Shared paging updates

Location:
trunk/src/VBox/VMM/VMMR0
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/GMMR0.cpp

    r29138 r29168  
    214214    struct GMMPAGESHARED
    215215    {
    216         /** The reference count. */
    217         uint32_t    cRefs;
     216        /** The guest page frame number. (Max addressable: 2 ^ 44 - 16) */
     217        uint32_t    pfn;
     218        /** The reference count (64K VMs). */
     219        uint32_t    cRefs : 16;
    218220        /** Reserved. Checksum or something? Two hGVMs for forking? */
    219         uint32_t    u30Reserved : 30;
     221        uint32_t    u30Reserved : 14;
    220222        /** The page state. */
    221223        uint32_t    u2State : 2;
     
    24022404        if (RT_UNLIKELY(pGVM->gmm.s.Allocated.cBasePages < cPages))
    24032405        {
    2404             Log(("gmmR0FreePages: allocated=%#llx cPages=%#x!\n", pGVM->gmm.s.Allocated.cBasePages, cPages));
     2406            Log(("GMMR0FreeLargePage: allocated=%#llx cPages=%#x!\n", pGVM->gmm.s.Allocated.cBasePages, cPages));
    24052407            RTSemFastMutexRelease(pGMM->Mtx);
    24062408            return VERR_GMM_ATTEMPT_TO_FREE_TOO_MUCH;
     
    31883190}
    31893191
     3192/**
     3193 * Check if a chunk is mapped into the specified VM
     3194 *
     3195 * @returns mapped yes/no
     3196 * @param   pGVM        Pointer to the Global VM structure.
     3197 * @param   pChunk      Pointer to the chunk to be mapped.
     3198 * @param   ppvR3       Where to store the ring-3 address of the mapping.
     3199 */
     3200static int gmmR0IsChunkMapped(PGVM pGVM, PGMMCHUNK pChunk, PRTR3PTR ppvR3)
     3201{
     3202    /*
     3203     * Check to see if the chunk is already mapped.
     3204     */
     3205    for (uint32_t i = 0; i < pChunk->cMappings; i++)
     3206    {
     3207        Assert(pChunk->paMappings[i].pGVM && pChunk->paMappings[i].MapObj != NIL_RTR0MEMOBJ);
     3208        if (pChunk->paMappings[i].pGVM == pGVM)
     3209        {
     3210            *ppvR3 = RTR0MemObjAddressR3(pChunk->paMappings[i].MapObj);
     3211            return true;
     3212        }
     3213    }
     3214    *ppvR3 = NULL;
     3215    return false;
     3216}
    31903217
    31913218/**
     
    34053432        if (!pRecVM)
    34063433        {
    3407             pRecVM = (PGMMSHAREDMODULEPERVM)RTMemAllocZ(sizeof(*pRecVM));
     3434            pRecVM = (PGMMSHAREDMODULEPERVM)RTMemAllocZ(RT_OFFSETOF(GMMSHAREDMODULEPERVM, aRegions[cRegions]));
    34083435            if (!pRecVM)
    34093436            {
     
    34203447                pRecVM->aRegions[i].cbRegion          = pRegions[i].cbRegion;
    34213448                pRecVM->aRegions[i].u32Alignment      = 0;
    3422                 pRecVM->aRegions[i].paHCPhysAndPageID = 0; /* uninitialized. */
     3449                pRecVM->aRegions[i].paHCPhysPageID    = NULL; /* uninitialized. */
    34233450            }
    34243451
     
    34323459
    34333460        /* Check if this module is already globally registered. */
    3434         PGMMSHAREDMODULE pRec = (PGMMSHAREDMODULE)RTAvlGCPtrGet(&pGMM->pGlobalSharedModuleTree, GCBaseAddr);
    3435         if (!pRec)
     3461        PGMMSHAREDMODULE pGlobalModule = (PGMMSHAREDMODULE)RTAvlGCPtrGet(&pGMM->pGlobalSharedModuleTree, GCBaseAddr);
     3462        if (!pGlobalModule)
    34363463        {
    34373464            Assert(fNewModule);
    34383465            Assert(!pRecVM->fCollision);
    34393466
    3440             pRec = (PGMMSHAREDMODULE)RTMemAllocZ(RT_OFFSETOF(GMMSHAREDMODULE, aRegions[cRegions]));
    3441             if (!pRec)
     3467            pGlobalModule = (PGMMSHAREDMODULE)RTMemAllocZ(RT_OFFSETOF(GMMSHAREDMODULE, aRegions[cRegions]));
     3468            if (!pGlobalModule)
    34423469            {
    34433470                AssertFailed();
     
    34463473            }
    34473474
    3448             pRec->Core.Key = GCBaseAddr;
    3449             pRec->cbModule = cbModule;
     3475            pGlobalModule->Core.Key = GCBaseAddr;
     3476            pGlobalModule->cbModule = cbModule;
    34503477            /* Input limit already safe; no need to check again. */
    34513478            /** todo replace with RTStrCopy */
    3452             strcpy(pRec->szName, pszModuleName);
    3453             strcpy(pRec->szVersion, pszVersion);
    3454 
    3455             pRec->cRegions = cRegions;
     3479            strcpy(pGlobalModule->szName, pszModuleName);
     3480            strcpy(pGlobalModule->szVersion, pszVersion);
     3481
     3482            pGlobalModule->cRegions = cRegions;
    34563483
    34573484            for (unsigned i = 0; i < cRegions; i++)
    34583485            {
    3459                 pRec->aRegions[i].GCRegionAddr      = pRegions[i].GCRegionAddr;
    3460                 pRec->aRegions[i].cbRegion          = pRegions[i].cbRegion;
    3461                 pRec->aRegions[i].u32Alignment      = 0;
    3462                 pRec->aRegions[i].paHCPhysAndPageID = 0; /* uninitialized. */
     3486                pGlobalModule->aRegions[i].GCRegionAddr      = pRegions[i].GCRegionAddr;
     3487                pGlobalModule->aRegions[i].cbRegion          = pRegions[i].cbRegion;
     3488                pGlobalModule->aRegions[i].u32Alignment      = 0;
     3489                pGlobalModule->aRegions[i].paHCPhysPageID    = NULL; /* uninitialized. */
    34633490            }
    34643491
    34653492            /* Save reference. */
    3466             pRecVM->pSharedModule = pRec;
     3493            pRecVM->pGlobalModule = pGlobalModule;
    34673494            pRecVM->fCollision    = false;
    3468             pRec->cUsers++;
     3495            pGlobalModule->cUsers++;
    34693496            rc = VINF_SUCCESS;
    34703497        }
    34713498        else
    34723499        {
    3473             Assert(pRec->cUsers > 0);
     3500            Assert(pGlobalModule->cUsers > 0);
    34743501
    34753502            /* Make sure the name and version are identical. */
    34763503            /** todo replace with RTStrNCmp */
    3477             if (    !strcmp(pRec->szName, pszModuleName)
    3478                 &&  !strcmp(pRec->szVersion, pszVersion))
     3504            if (    !strcmp(pGlobalModule->szName, pszModuleName)
     3505                &&  !strcmp(pGlobalModule->szVersion, pszVersion))
    34793506            {
    34803507                Assert(!pRecVM->fCollision);
    34813508
    34823509                /* Save reference. */
    3483                 pRecVM->pSharedModule = pRec;
     3510                pRecVM->pGlobalModule = pGlobalModule;
    34843511                pRecVM->fCollision    = false;
    34853512                if (fNewModule)
    3486                     pRec->cUsers++;
     3513                    pGlobalModule->cUsers++;
    34873514                rc = VINF_SUCCESS;
    34883515            }
     
    35683595        /* Force pRec to go out of scope after freeing it. */
    35693596        {
    3570             PGMMSHAREDMODULE pRec = pRecVM->pSharedModule;
     3597            PGMMSHAREDMODULE pRec = pRecVM->pGlobalModule;
    35713598            Assert(pRec);
    35723599            Assert(pRec->cUsers);
     
    35773604                /* @todo free shared pages. */
    35783605                for (unsigned i = 0; i < pRec->cRegions; i++)
    3579                     if (pRec->aRegions[i].paHCPhysAndPageID)
    3580                         RTMemFree(pRec->aRegions[i].paHCPhysAndPageID);
     3606                    if (pRec->aRegions[i].paHCPhysPageID)
     3607                        RTMemFree(pRec->aRegions[i].paHCPhysPageID);
    35813608
    35823609                RTMemFree(pRec);
    35833610            }
    35843611        }
    3585 
     3612        /* Free all the shared pages we refence here. */
    35863613        for (unsigned i = 0; i < pRecVM->cRegions; i++)
    3587             if (pRecVM->aRegions[i].paHCPhysAndPageID)
    3588                 RTMemFree(pRecVM->aRegions[i].paHCPhysAndPageID);
     3614        {
     3615            PGMMSHAREDREGIONDESC pRegion = &pRecVM->aRegions[i];
     3616
     3617            if (pRegion->paHCPhysPageID)
     3618            {
     3619                unsigned cPages = pRegion->cbRegion >> PAGE_SHIFT;
     3620
     3621                for (unsigned j = 0; j < cPages; j++)
     3622                {
     3623                    if (pRegion->paHCPhysPageID[j] != NIL_GMM_PAGEID)
     3624                    {
     3625                        GMMFREEPAGEDESC PageDesc;
     3626
     3627                        PageDesc.idPage = pRegion->paHCPhysPageID[j];
     3628                        rc = gmmR0FreePages(pGMM, pGVM, 1, &PageDesc, GMMACCOUNT_BASE);
     3629                        AssertRC(rc);
     3630                    }
     3631                }
     3632
     3633                RTMemFree(pRecVM->aRegions[i].paHCPhysPageID);
     3634            }
     3635        }
    35893636        RTMemFree(pRecVM);
    35903637
     
    36273674 * Checks specified shared module range for changes
    36283675 *
     3676 * Performs the following tasks:
     3677 * - if a shared page is new, then it changes the GMM page type to shared and returns it in the paHCPhysPageID array
     3678 * - if a shared page already exists, then it checks if the VM page is identical and if so frees the VM page and returns the shared page in the paHCPhysPageID array
     3679 *
    36293680 * @returns VBox status code.
    36303681 * @param   pVM                 VM handle
     
    36333684 * @param   idxRegion           Region index
    36343685 * @param   cPages              Number of entries in the paHCPhysAndPageID array
    3635  * @param   paHCPhysAndPageID   Host physical address and the Page ID array
    3636  */
    3637 GMMR0DECL(int)  GMMR0SharedModuleCheckRange(PVM pVM, VMCPUID idCpu, PGMMREGISTERSHAREDMODULEREQ pReq, unsigned idxRegion, unsigned cPages, PRTHCPHYS paHCPhysAndPageID)
     3686 * @param   paPageDesc          Page descriptor array (in/out)
     3687 */
     3688GMMR0DECL(int) GMMR0SharedModuleCheckRange(PVM pVM, VMCPUID idCpu, PGMMREGISTERSHAREDMODULEREQ pReq, unsigned idxRegion, unsigned cPages, PGMMSHAREDPAGEDESC paPageDesc)
    36383689{
    36393690    AssertReturn(idxRegion < pReq->cRegions, VERR_INVALID_PARAMETER);
     
    36573708    if (GMM_CHECK_SANITY_UPON_ENTERING(pGMM))
    36583709    {
    3659         PGMMSHAREDMODULEPERVM pRecVM = (PGMMSHAREDMODULEPERVM)RTAvlGCPtrGet(&pGVM->gmm.s.pSharedModuleTree, pReq->GCBaseAddr);
    3660         if (!pRecVM)
    3661         {
     3710        PGMMSHAREDMODULEPERVM pLocalModule = (PGMMSHAREDMODULEPERVM)RTAvlGCPtrGet(&pGVM->gmm.s.pSharedModuleTree, pReq->GCBaseAddr);
     3711        if (    !pLocalModule
     3712            ||  pLocalModule->fCollision)
     3713        {
     3714            Assert(!pLocalModule);
    36623715            rc = VERR_PGM_SHARED_MODULE_NOT_FOUND;
    36633716            goto end;
    36643717        }
    3665 
     3718        PGMMSHAREDREGIONDESC pLocalRegion = &pLocalModule->aRegions[idxRegion];
     3719        if (!pLocalRegion->paHCPhysPageID)
     3720        {
     3721            /* First time; create a page descriptor array. */
     3722            pLocalRegion->paHCPhysPageID = (uint32_t *)RTMemAlloc(cPages * sizeof(*pLocalRegion->paHCPhysPageID));
     3723            if (!pLocalRegion->paHCPhysPageID)
     3724            {
     3725                AssertFailed();
     3726                rc = VERR_NO_MEMORY;
     3727                goto end;
     3728            }
     3729            /* Invalidate all descriptors. */
     3730            for (unsigned i = 0; i < cPages; i++)
     3731                pLocalRegion->paHCPhysPageID[i] = NIL_GMM_PAGEID;
     3732        }
     3733
     3734        PGMMSHAREDMODULE     pGlobalModule = pLocalModule->pGlobalModule;
     3735        PGMMSHAREDREGIONDESC pGlobalRegion = &pGlobalModule->aRegions[idxRegion];
     3736
     3737        if (!pGlobalRegion->paHCPhysPageID)
     3738        {
     3739            /* First time; create a page descriptor array. */
     3740            pGlobalRegion->paHCPhysPageID = (uint32_t *)RTMemAlloc(cPages * sizeof(*pGlobalRegion->paHCPhysPageID));
     3741            if (!pGlobalRegion->paHCPhysPageID)
     3742            {
     3743                AssertFailed();
     3744                rc = VERR_NO_MEMORY;
     3745                goto end;
     3746            }
     3747            /* Invalidate all descriptors. */
     3748            for (unsigned i = 0; i < cPages; i++)
     3749                pGlobalRegion->paHCPhysPageID[i] = NIL_GMM_PAGEID;
     3750        }
     3751
     3752        /* Check all pages in the region. */
    36663753        for (unsigned i = 0; i < cPages; i++)
    36673754        {
     3755            /* Valid page present? */
     3756            if (paPageDesc[i].uPageId != NIL_GMM_PAGEID)
     3757            {
     3758                /* We've seen this shared page for the first time? */
     3759                if (pGlobalRegion->paHCPhysPageID[i] == NIL_GMM_PAGEID)
     3760                {
     3761                    Assert(pLocalRegion->paHCPhysPageID[i] == NIL_GMM_PAGEID);
     3762
     3763                    /* Easy case: just change the internal page type. */
     3764                    PGMMPAGE pPage = gmmR0GetPage(pGMM, paPageDesc[i].uPageId);
     3765                    if (!pPage)
     3766                    {
     3767                        AssertFailed();
     3768                        rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
     3769                        goto end;
     3770                    }
     3771                    Assert(paPageDesc[i].HCPhys == (pPage->Private.pfn << 12));
     3772                    pPage->Shared.pfn     = pPage->Private.pfn;     /* same location */
     3773                    pPage->Shared.cRefs   = 1;
     3774                    pPage->Common.u2State = GMM_PAGE_STATE_SHARED;
     3775
     3776                    /* Keep track of these references. */
     3777                    pLocalRegion->paHCPhysPageID[i]  = paPageDesc[i].uPageId;
     3778                    pGlobalRegion->paHCPhysPageID[i] = paPageDesc[i].uPageId;
     3779                }
     3780                else
     3781                {
     3782                    Assert(pLocalRegion->paHCPhysPageID[i] != pGlobalRegion->paHCPhysPageID[i]);
     3783
     3784                    PGMMPAGE pPage = gmmR0GetPage(pGMM, paPageDesc[i].uPageId);
     3785                    if (!pPage)
     3786                    {
     3787                        AssertFailed();
     3788                        rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
     3789                        goto end;
     3790                    }
     3791                    Assert(pPage->Common.u2State == GMM_PAGE_STATE_SHARED);
     3792
     3793                    PGMMCHUNK pChunk = gmmR0GetChunk(pGMM, paPageDesc[i].uPageId >> GMM_CHUNKID_SHIFT);
     3794                    Assert(pChunk); /* can't fail as gmmR0GetPage succeeded. */
     3795                    uint8_t *pbR3Page, *pbR3Chunk;
     3796
     3797                    /* Get the virtual address of the physical page; map the chunk into the VM process if not already done. */
     3798                    if (!gmmR0IsChunkMapped(pGVM, pChunk, (PRTR3PTR)&pbR3Chunk))
     3799                    {
     3800                        rc = gmmR0MapChunk(pGMM, pGVM, pChunk, (PRTR3PTR)&pbR3Chunk);
     3801                        if (rc != VINF_SUCCESS)
     3802                        {
     3803                            AssertRC(rc);
     3804                            goto end;
     3805                        }
     3806                    }
     3807                    pbR3Page = pbR3Chunk + ((paPageDesc[i].uPageId & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
     3808
     3809                    /* Free the old local page. */
     3810                    GMMFREEPAGEDESC PageDesc;
     3811
     3812                    PageDesc.idPage = pLocalRegion->paHCPhysPageID[i];
     3813                    rc = gmmR0FreePages(pGMM, pGVM, 1, &PageDesc, GMMACCOUNT_BASE);
     3814                    AssertRC(rc);
     3815
     3816                    /* Pass along the new physical address & page id. */
     3817                    paPageDesc[i].HCPhys  = (pPage->Private.pfn << 12);
     3818                    paPageDesc[i].uPageId = pGlobalRegion->paHCPhysPageID[i];
     3819
     3820                    pLocalRegion->paHCPhysPageID[i] = pGlobalRegion->paHCPhysPageID[i];
     3821                }
     3822            }
     3823#ifdef LOG_ENABLED
     3824            else
     3825            if (pLocalRegion->paHCPhysPageID[i] != NIL_GMM_PAGEID)
     3826            {
     3827                /* Page was removed. */
     3828                Log(("GMMR0SharedModuleCheckRange: page id %x not present anymore\n", pLocalRegion->paHCPhysPageID[i]));
     3829            }
     3830#endif
    36683831        }
    36693832
  • trunk/src/VBox/VMM/VMMR0/GMMR0Internal.h

    r29138 r29168  
    4949    /** Alignment. */
    5050    uint32_t            u32Alignment;
    51     /** Pointer to physical page address array. */
    52     PRTHCPHYS           paHCPhysAndPageID;
     51    /** Pointer to physical page id array. */
     52    uint32_t           *paHCPhysPageID;
    5353} GMMSHAREDREGIONDESC;
    5454/** Pointer to a GMMSHAREDREGIONDESC. */
     
    8585typedef struct GMMSHAREDMODULEPERVM
    8686{
    87     /* Tree node. */
     87    /** Tree node. */
    8888    AVLGCPTRNODECORE            Core;
    8989
    90     /* Pointer to global shared module info. */
    91     PGMMSHAREDMODULE            pSharedModule;
     90    /** Pointer to global shared module info. */
     91    PGMMSHAREDMODULE            pGlobalModule;
    9292
    93     /* Set if another VM registered a different shared module at the same base address. */
     93    /** Set if another VM registered a different shared module at the same base address. */
    9494    bool                        fCollision;
    95     /** Align at 8 byte boundary */
    96     bool                        abAlignment[7];
     95    /** Alignment. */
     96    bool                        bAlignment;
    9797
    98     /** Number of regions in the aRegions array. */
     98    /** Number of regions. */
    9999    unsigned                    cRegions;
    100 
    101100    /** Shared region descriptor(s). */
    102101    GMMSHAREDREGIONDESC         aRegions[1];
  • trunk/src/VBox/VMM/VMMR0/PGMR0.cpp

    r29138 r29168  
    313313VMMR0DECL(int) PGMR0SharedModuleCheck(PVM pVM, PVMCPU pVCpu, PGMMREGISTERSHAREDMODULEREQ pReq)
    314314{
    315     int rc = VINF_SUCCESS;
    316     PRTHCPHYS paHCPhysAndPageID = NULL;
    317     uint32_t  cbPreviousRegion  = 0;
     315    int                rc = VINF_SUCCESS;
     316    PGMMSHAREDPAGEDESC paPageDesc = NULL;
     317    uint32_t           cbPreviousRegion  = 0;
     318    bool               fFlushTLBs = false;
    318319
    319320    /*
     
    338339        if (cbPreviousRegion < cbRegion)
    339340        {
    340             if (paHCPhysAndPageID)
    341                 RTMemFree(paHCPhysAndPageID);
    342 
    343             paHCPhysAndPageID = (PRTHCPHYS)RTMemAlloc((cbRegion << PAGE_SHIFT) * sizeof(*paHCPhysAndPageID));
    344             if (!paHCPhysAndPageID)
     341            if (paPageDesc)
     342                RTMemFree(paPageDesc);
     343
     344            paPageDesc = (PGMMSHAREDPAGEDESC)RTMemAlloc((cbRegion << PAGE_SHIFT) * sizeof(*paPageDesc));
     345            if (!paPageDesc)
    345346            {
    346347                AssertFailed();
     
    365366                {
    366367                    fValidChanges = true;
    367                     paHCPhysAndPageID[idxPage] = pPage->HCPhysAndPageID;
     368                    paPageDesc[idxPage].uPageId = PGM_PAGE_GET_PAGEID(pPage);
     369                    paPageDesc[idxPage].HCPhys  = PGM_PAGE_GET_HCPHYS(pPage);
     370                    paPageDesc[idxPage].GCPhys  = GCPhys;
    368371                }
    369372                else
    370                     paHCPhysAndPageID[idxPage] = NIL_RTHCPHYS;
     373                    paPageDesc[idxPage].uPageId = NIL_GMM_PAGEID;
    371374            }
    372375            else
    373                 paHCPhysAndPageID[idxPage] = NIL_RTHCPHYS;
     376                paPageDesc[idxPage].uPageId = NIL_GMM_PAGEID;
    374377
    375378            idxPage++;
     
    380383        if (fValidChanges)
    381384        {
    382             rc = GMMR0SharedModuleCheckRange(pVM, pVCpu->idCpu, pReq, i, idxPage, paHCPhysAndPageID);
     385            rc = GMMR0SharedModuleCheckRange(pVM, pVCpu->idCpu, pReq, i, idxPage, paPageDesc);
    383386            AssertRC(rc);
    384387            if (RT_FAILURE(rc))
    385388                break;
     389
     390            for (unsigned i = 0; i < idxPage; i++)
     391            {
     392                /* Any change for this page? */
     393                if (paPageDesc[i].uPageId != NIL_GMM_PAGEID)
     394                {
     395                    /** todo: maybe cache these to prevent the nth lookup. */
     396                    PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, paPageDesc[idxPage].GCPhys);
     397                    if (!pPage)
     398                    {
     399                        /* Should never happen. */
     400                        AssertFailed();
     401                        rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
     402                        goto end;
     403                    }
     404                    Assert(!PGM_PAGE_IS_SHARED(pPage));
     405
     406                    if (paPageDesc[idxPage].HCPhys != PGM_PAGE_GET_HCPHYS(pPage))
     407                    {
     408                        bool fFlush = false;
     409
     410                        /* Page was replaced by an existing shared version of it; dereference the page first. */
     411                        rc = pgmPoolTrackUpdateGCPhys(pVM, paPageDesc[idxPage].GCPhys, pPage, true /* clear the entries */, &fFlush);
     412                        if (RT_FAILURE(rc))
     413                        {
     414                            AssertRC(rc);
     415                            goto end;
     416                        }
     417                        Assert(rc == VINF_SUCCESS || (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3) && (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_CLEAR_PGM_POOL)));
     418                        if (rc = VINF_SUCCESS)
     419                            fFlushTLBs |= fFlush;
     420
     421                        /* Update the physical address and page id now. */
     422                        PGM_PAGE_SET_HCPHYS(pPage, paPageDesc[idxPage].HCPhys);
     423                        PGM_PAGE_SET_PAGEID(pPage, paPageDesc[idxPage].uPageId);
     424                    }
     425                    /* else nothing changed (== this page is now a shared page), so no need to flush anything. */
     426
     427                    PGM_PAGE_SET_STATE(pPage, PGM_PAGE_STATE_SHARED);
     428                }
     429            }
    386430        }
    387431    }
     
    389433end:
    390434    pgmUnlock(pVM);
    391     if (paHCPhysAndPageID)
    392         RTMemFree(paHCPhysAndPageID);
     435    if (fFlushTLBs)
     436        PGM_INVL_ALL_VCPU_TLBS(pVM);
     437
     438    if (paPageDesc)
     439        RTMemFree(paPageDesc);
    393440
    394441    return rc;
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