VirtualBox

Changeset 30783 in vbox


Ignore:
Timestamp:
Jul 12, 2010 9:19:24 AM (15 years ago)
Author:
vboxsync
Message:

Rewrote shared page handling to be more fault tolerant.

Location:
trunk
Files:
4 edited

Legend:

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

    r30660 r30783  
    479479/** Inconsistent local and global registration records. */
    480480#define VERR_PGM_SHARED_MODULE_REGISTRATION_INCONSISTENCY (-1650)
    481 /** First shared module check. */
    482 #define VERR_PGM_SHARED_MODULE_FIRST_CHECK      (-1651)
    483481/** @} */
    484482
  • trunk/include/VBox/gmm.h

    r30660 r30783  
    561561typedef GMMSHAREDPAGEDESC *PGMMSHAREDPAGEDESC;
    562562
    563 GMMR0DECL(int) GMMR0SharedModuleCheckRange(PGVM pGVM, PGMMSHAREDMODULE pModule, unsigned idxRegion, unsigned cPages, PGMMSHAREDPAGEDESC paPageDesc);
     563GMMR0DECL(int) GMMR0SharedModuleCheckPage(PGVM pGVM, PGMMSHAREDMODULE pModule, unsigned idxRegion, unsigned idxPage, PGMMSHAREDPAGEDESC pPageDesc);
    564564
    565565/**
  • trunk/src/VBox/VMM/VMMR0/GMMR0.cpp

    r30769 r30783  
    38193819 *
    38203820 * Performs the following tasks:
    3821  * - if a shared page is new, then it changes the GMM page type to shared and returns it in the paPageDesc array
    3822  * - 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 paPageDesc array
     3821 * - if a shared page is new, then it changes the GMM page type to shared and returns it in the pPageDesc descriptor
     3822 * - 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 pPageDesc descriptor
    38233823 *
    38243824 * Note: assumes the caller has acquired the GMM semaphore!!
     
    38293829 * @param   pModule             Module description
    38303830 * @param   idxRegion           Region index
    3831  * @param   cPages              Number of entries in the paPageDesc array
    3832  * @param   paPageDesc          Page descriptor array (in/out)
    3833  */
    3834 GMMR0DECL(int) GMMR0SharedModuleCheckRange(PGVM pGVM, PGMMSHAREDMODULE pModule, unsigned idxRegion, unsigned cPages, PGMMSHAREDPAGEDESC paPageDesc)
     3831 * @param   idxPage             Page index
     3832 * @param   paPageDesc          Page descriptor
     3833 */
     3834GMMR0DECL(int) GMMR0SharedModuleCheckPage(PGVM pGVM, PGMMSHAREDMODULE pModule, unsigned idxRegion, unsigned idxPage, PGMMSHAREDPAGEDESC pPageDesc)
    38353835{
    38363836    int rc = VINF_SUCCESS;
    38373837    PGMM pGMM;
    38383838    GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR);
     3839    unsigned cPages = pModule->aRegions[idxRegion].cbRegion >> PAGE_SHIFT;
    38393840
    38403841    AssertReturn(idxRegion < pModule->cRegions, VERR_INVALID_PARAMETER);
    3841     AssertReturn(cPages == (pModule->aRegions[idxRegion].cbRegion >> PAGE_SHIFT), VERR_INVALID_PARAMETER);
    3842 
    3843     Log(("GMMR0SharedModuleCheckRange %s base %RGv region %d cPages %d\n", pModule->szName, pModule->Core.Key, idxRegion, cPages));
     3842    AssertReturn(idxPage < cPages, VERR_INVALID_PARAMETER);
     3843
     3844    LogFlow(("GMMR0SharedModuleCheckRange %s base %RGv region %d idxPage %d\n", pModule->szName, pModule->Core.Key, idxRegion, idxPage));
    38443845
    38453846    PGMMSHAREDREGIONDESC pGlobalRegion = &pModule->aRegions[idxRegion];
    3846 
    38473847    if (!pGlobalRegion->paHCPhysPageID)
    38483848    {
     
    38613861    }
    38623862
    3863     /* Check all pages in the region. */
    3864     for (unsigned i = 0; i < cPages; i++)
    3865     {
    3866         /* Valid page present? */
    3867         if (paPageDesc[i].uHCPhysPageId != NIL_GMM_PAGEID)
    3868         {
    3869             /* We've seen this shared page for the first time? */
    3870             if (pGlobalRegion->paHCPhysPageID[i] == NIL_GMM_PAGEID)
     3863    /* We've seen this shared page for the first time? */
     3864    if (pGlobalRegion->paHCPhysPageID[idxPage] == NIL_GMM_PAGEID)
     3865    {
     3866new_shared_page:
     3867        Log(("New shared page guest %RGp host %RHp\n", pPageDesc->GCPhys, pPageDesc->HCPhys));
     3868
     3869        /* Easy case: just change the internal page type. */
     3870        PGMMPAGE pPage = gmmR0GetPage(pGMM, pPageDesc->uHCPhysPageId);
     3871        if (!pPage)
     3872        {
     3873            AssertFailed();
     3874            rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
     3875            goto end;
     3876        }
     3877
     3878        AssertMsg(pPageDesc->GCPhys == (pPage->Private.pfn << 12), ("desc %RGp gmm %RGp\n", pPageDesc->HCPhys, (pPage->Private.pfn << 12)));
     3879
     3880        gmmR0ConvertToSharedPage(pGMM, pGVM, pPageDesc->HCPhys, pPageDesc->uHCPhysPageId, pPage);
     3881
     3882        /* Keep track of these references. */
     3883        pGlobalRegion->paHCPhysPageID[idxPage] = pPageDesc->uHCPhysPageId;
     3884    }
     3885    else
     3886    {
     3887        uint8_t  *pbLocalPage, *pbSharedPage;
     3888        uint8_t  *pbChunk;
     3889        PGMMCHUNK pChunk;
     3890
     3891        Assert(pPageDesc->uHCPhysPageId != pGlobalRegion->paHCPhysPageID[idxPage]);
     3892
     3893        Log(("Replace existing page guest %RGp host %RHp id %x -> id %x\n", pPageDesc->GCPhys, pPageDesc->HCPhys, pPageDesc->uHCPhysPageId, pGlobalRegion->paHCPhysPageID[idxPage]));
     3894
     3895        /* Get the shared page source. */
     3896        PGMMPAGE pPage = gmmR0GetPage(pGMM, pGlobalRegion->paHCPhysPageID[idxPage]);
     3897        if (!pPage)
     3898        {
     3899            AssertFailed();
     3900            rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
     3901            goto end;
     3902        }
     3903        if (pPage->Common.u2State != GMM_PAGE_STATE_SHARED)
     3904        {
     3905            /* Page was freed at some point; invalidate this entry. */
     3906            /** todo this isn't really bullet proof. */
     3907            Log(("Old shared page was freed -> create a new one\n"));
     3908            pGlobalRegion->paHCPhysPageID[idxPage] = NIL_GMM_PAGEID;
     3909            goto new_shared_page; /* ugly goto */
     3910        }
     3911
     3912        Log(("Replace existing page guest host %RHp -> %RHp\n", pPageDesc->HCPhys, ((uint64_t)pPage->Shared.pfn) << PAGE_SHIFT));
     3913
     3914        /* Calculate the virtual address of the local page. */
     3915        pChunk = gmmR0GetChunk(pGMM, pPageDesc->uHCPhysPageId >> GMM_CHUNKID_SHIFT);
     3916        if (pChunk)
     3917        {
     3918            if (!gmmR0IsChunkMapped(pGVM, pChunk, (PRTR3PTR)&pbChunk))
    38713919            {
    3872 new_shared_page:
    3873                 Log(("New shared page guest %RGp host %RHp\n", paPageDesc[i].GCPhys, paPageDesc[i].HCPhys));
    3874 
    3875                 /* Easy case: just change the internal page type. */
    3876                 PGMMPAGE pPage = gmmR0GetPage(pGMM, paPageDesc[i].uHCPhysPageId);
    3877                 if (!pPage)
    3878                 {
    3879                     AssertFailed();
    3880                     rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    3881                     goto end;
    3882                 }
    3883 
    3884                 AssertMsg(paPageDesc[i].GCPhys == (pPage->Private.pfn << 12), ("desc %RGp gmm %RGp\n", paPageDesc[i].HCPhys, (pPage->Private.pfn << 12)));
    3885 
    3886                 gmmR0ConvertToSharedPage(pGMM, pGVM, paPageDesc[i].HCPhys, paPageDesc[i].uHCPhysPageId, pPage);
    3887 
    3888                 /* Keep track of these references. */
    3889                 pGlobalRegion->paHCPhysPageID[i] = paPageDesc[i].uHCPhysPageId;
     3920                AssertFailed();
     3921                rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
     3922                goto end;
    38903923            }
    3891             else
     3924            pbLocalPage = pbChunk + ((pPageDesc->uHCPhysPageId & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
     3925        }
     3926        else
     3927        {
     3928            AssertFailed();
     3929            rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
     3930            goto end;
     3931        }
     3932
     3933        /* Calculate the virtual address of the shared page. */
     3934        pChunk = gmmR0GetChunk(pGMM, pGlobalRegion->paHCPhysPageID[idxPage] >> GMM_CHUNKID_SHIFT);
     3935        Assert(pChunk); /* can't fail as gmmR0GetPage succeeded. */
     3936
     3937        /* Get the virtual address of the physical page; map the chunk into the VM process if not already done. */
     3938        if (!gmmR0IsChunkMapped(pGVM, pChunk, (PRTR3PTR)&pbChunk))
     3939        {
     3940            Log(("Map chunk into process!\n"));
     3941            rc = gmmR0MapChunk(pGMM, pGVM, pChunk, (PRTR3PTR)&pbChunk);
     3942            if (rc != VINF_SUCCESS)
    38923943            {
    3893                 uint8_t  *pbLocalPage, *pbSharedPage;
    3894                 uint8_t  *pbChunk;
    3895                 PGMMCHUNK pChunk;
    3896 
    3897                 Assert(paPageDesc[i].uHCPhysPageId != pGlobalRegion->paHCPhysPageID[i]);
    3898 
    3899                 Log(("Replace existing page guest %RGp host %RHp id %x -> id %x\n", paPageDesc[i].GCPhys, paPageDesc[i].HCPhys, paPageDesc[i].uHCPhysPageId, pGlobalRegion->paHCPhysPageID[i]));
    3900 
    3901                 /* Get the shared page source. */
    3902                 PGMMPAGE pPage = gmmR0GetPage(pGMM, pGlobalRegion->paHCPhysPageID[i]);
    3903                 if (!pPage)
    3904                 {
    3905                     AssertFailed();
    3906                     rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    3907                     goto end;
    3908                 }
    3909                 if (pPage->Common.u2State != GMM_PAGE_STATE_SHARED)
    3910                 {
    3911                     /* Page was freed at some point; invalidate this entry. */
    3912                     /** todo this isn't really bullet proof. */
    3913                     Log(("Old shared page was freed -> create a new one\n"));
    3914                     pGlobalRegion->paHCPhysPageID[i] = NIL_GMM_PAGEID;
    3915                     goto new_shared_page; /* ugly goto */
    3916                 }
    3917 
    3918                 Log(("Replace existing page guest host %RHp -> %RHp\n", paPageDesc[i].HCPhys, ((uint64_t)pPage->Shared.pfn) << PAGE_SHIFT));
    3919 
    3920                 /* Calculate the virtual address of the local page. */
    3921                 pChunk = gmmR0GetChunk(pGMM, paPageDesc[i].uHCPhysPageId >> GMM_CHUNKID_SHIFT);
    3922                 if (pChunk)
    3923                 {
    3924                     if (!gmmR0IsChunkMapped(pGVM, pChunk, (PRTR3PTR)&pbChunk))
    3925                     {
    3926                         AssertFailed();
    3927                         rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    3928                         goto end;
    3929                     }
    3930                     pbLocalPage = pbChunk + ((paPageDesc[i].uHCPhysPageId & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
    3931                 }
    3932                 else
    3933                 {
    3934                     AssertFailed();
    3935                     rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    3936                     goto end;
    3937                 }
    3938 
    3939                 /* Calculate the virtual address of the shared page. */
    3940                 pChunk = gmmR0GetChunk(pGMM, pGlobalRegion->paHCPhysPageID[i] >> GMM_CHUNKID_SHIFT);
    3941                 Assert(pChunk); /* can't fail as gmmR0GetPage succeeded. */
    3942 
    3943                 /* Get the virtual address of the physical page; map the chunk into the VM process if not already done. */
    3944                 if (!gmmR0IsChunkMapped(pGVM, pChunk, (PRTR3PTR)&pbChunk))
    3945                 {
    3946                     Log(("Map chunk into process!\n"));
    3947                     rc = gmmR0MapChunk(pGMM, pGVM, pChunk, (PRTR3PTR)&pbChunk);
    3948                     if (rc != VINF_SUCCESS)
    3949                     {
    3950                         AssertRC(rc);
    3951                         goto end;
    3952                     }
    3953                 }
    3954                 pbSharedPage = pbChunk + ((pGlobalRegion->paHCPhysPageID[i] & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
    3955 
    3956                 /** todo write ASMMemComparePage. */
    3957                 if (memcmp(pbSharedPage, pbLocalPage, PAGE_SIZE))
    3958                 {
    3959                     Log(("Unexpected differences found between local and shared page; skip\n"));
    3960                     /* Signal to the caller that this one hasn't changed. */
    3961                     paPageDesc[i].uHCPhysPageId = NIL_GMM_PAGEID;
    3962                     continue;
    3963                 }
    3964 
    3965                 /* Free the old local page. */
    3966                 GMMFREEPAGEDESC PageDesc;
    3967 
    3968                 PageDesc.idPage = paPageDesc[i].uHCPhysPageId;
    3969                 rc = gmmR0FreePages(pGMM, pGVM, 1, &PageDesc, GMMACCOUNT_BASE);
    3970                 AssertRCReturn(rc, rc);
    3971 
    3972                 gmmR0UseSharedPage(pGMM, pGVM, pPage);
    3973 
    3974                 /* Pass along the new physical address & page id. */
    3975                 paPageDesc[i].HCPhys        = ((uint64_t)pPage->Shared.pfn) << PAGE_SHIFT;
    3976                 paPageDesc[i].uHCPhysPageId = pGlobalRegion->paHCPhysPageID[i];
     3944                AssertRC(rc);
     3945                goto end;
    39773946            }
    39783947        }
     3948        pbSharedPage = pbChunk + ((pGlobalRegion->paHCPhysPageID[idxPage] & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
     3949
     3950        /** todo write ASMMemComparePage. */
     3951        if (memcmp(pbSharedPage, pbLocalPage, PAGE_SIZE))
     3952        {
     3953            Log(("Unexpected differences found between local and shared page; skip\n"));
     3954            /* Signal to the caller that this one hasn't changed. */
     3955            pPageDesc->uHCPhysPageId = NIL_GMM_PAGEID;
     3956            goto end;
     3957        }
     3958
     3959        /* Free the old local page. */
     3960        GMMFREEPAGEDESC PageDesc;
     3961
     3962        PageDesc.idPage = pPageDesc->uHCPhysPageId;
     3963        rc = gmmR0FreePages(pGMM, pGVM, 1, &PageDesc, GMMACCOUNT_BASE);
     3964        AssertRCReturn(rc, rc);
     3965
     3966        gmmR0UseSharedPage(pGMM, pGVM, pPage);
     3967
     3968        /* Pass along the new physical address & page id. */
     3969        pPageDesc->HCPhys        = ((uint64_t)pPage->Shared.pfn) << PAGE_SHIFT;
     3970        pPageDesc->uHCPhysPageId = pGlobalRegion->paHCPhysPageID[idxPage];
    39793971    }
    39803972end:
  • trunk/src/VBox/VMM/VMMR0/PGMR0SharedPage.cpp

    r30761 r30783  
    4747{
    4848    int                rc = VINF_SUCCESS;
    49     PGMMSHAREDPAGEDESC paPageDesc = NULL;
    50     uint32_t           cbPreviousRegion  = 0;
     49    GMMSHAREDPAGEDESC  PageDesc;
    5150    bool               fFlushTLBs = false;
    5251    PVMCPU             pVCpu = &pVM->aCpus[idCpu];
     
    6564        unsigned cbRegion = pRegions[idxRegion].cbRegion & ~0xfff;
    6665        unsigned idxPage = 0;
    67         bool     fValidChanges = false;
    68 
    69         if (cbPreviousRegion < cbRegion)
    70         {
    71             if (paPageDesc)
    72                 RTMemFree(paPageDesc);
    73 
    74             paPageDesc = (PGMMSHAREDPAGEDESC)RTMemAlloc((cbRegion >> PAGE_SHIFT) * sizeof(*paPageDesc));
    75             if (!paPageDesc)
    76             {
    77                 AssertFailed();
    78                 rc = VERR_NO_MEMORY;
    79                 goto end;
    80             }
    81             cbPreviousRegion  = cbRegion;
    82         }
    8366
    8467        while (cbRegion)
     
    9780                    &&  PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED)
    9881                {
    99                     fValidChanges = true;
    100                     paPageDesc[idxPage].uHCPhysPageId = PGM_PAGE_GET_PAGEID(pPage);
    101                     paPageDesc[idxPage].HCPhys        = PGM_PAGE_GET_HCPHYS(pPage);
    102                     paPageDesc[idxPage].GCPhys        = GCPhys;
     82                    PageDesc.uHCPhysPageId = PGM_PAGE_GET_PAGEID(pPage);
     83                    PageDesc.HCPhys        = PGM_PAGE_GET_HCPHYS(pPage);
     84                    PageDesc.GCPhys        = GCPhys;
     85
     86                    rc = GMMR0SharedModuleCheckPage(pGVM, pModule, idxRegion, idxPage, &PageDesc);
     87                    if (rc == VINF_SUCCESS)
     88                    {
     89                        /* Any change for this page? */
     90                        if (PageDesc.uHCPhysPageId != NIL_GMM_PAGEID)
     91                        {
     92                            Assert(PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED);
     93
     94                            Log(("PGMR0SharedModuleCheck: shared page gc virt=%RGv phys %RGp host %RHp->%RHp\n", pRegions[idxRegion].GCRegionAddr + idxPage * PAGE_SIZE, PageDesc.GCPhys, PGM_PAGE_GET_HCPHYS(pPage), PageDesc.HCPhys));
     95                            if (PageDesc.HCPhys != PGM_PAGE_GET_HCPHYS(pPage))
     96                            {
     97                                bool fFlush = false;
     98
     99                                /* Page was replaced by an existing shared version of it; clear all references first. */
     100                                rc = pgmPoolTrackUpdateGCPhys(pVM, PageDesc.GCPhys, pPage, true /* clear the entries */, &fFlush);
     101                                Assert(rc == VINF_SUCCESS || (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3) && (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_CLEAR_PGM_POOL)));
     102                                if (rc == VINF_SUCCESS)
     103                                    fFlushTLBs |= fFlush;
     104
     105                                /* Update the physical address and page id now. */
     106                                PGM_PAGE_SET_HCPHYS(pPage, PageDesc.HCPhys);
     107                                PGM_PAGE_SET_PAGEID(pPage, PageDesc.uHCPhysPageId);
     108
     109                                /* Invalidate page map TLB entry for this page too. */
     110                                PGMPhysInvalidatePageMapTLBEntry(pVM, PageDesc.GCPhys);
     111                                pVM->pgm.s.cReusedSharedPages++;
     112                            }
     113                            /* else nothing changed (== this page is now a shared page), so no need to flush anything. */
     114
     115                            pVM->pgm.s.cSharedPages++;
     116                            pVM->pgm.s.cPrivatePages--;
     117                            PGM_PAGE_SET_STATE(pPage, PGM_PAGE_STATE_SHARED);
     118                        }
     119                    }
     120                    else
     121                        break;
    103122                }
    104                 else
    105                     paPageDesc[idxPage].uHCPhysPageId = NIL_GMM_PAGEID;
    106123            }
    107             else
    108                 paPageDesc[idxPage].uHCPhysPageId = NIL_GMM_PAGEID;
    109124
    110125            idxPage++;
     
    112127            cbRegion -= PAGE_SIZE;
    113128        }
    114 
    115         if (fValidChanges)
    116         {
    117             rc = GMMR0SharedModuleCheckRange(pGVM, pModule, idxRegion, idxPage, paPageDesc);
    118             AssertRC(rc);
    119             if (RT_FAILURE(rc))
    120                 break;
    121 
    122             for (unsigned i = 0; i < idxPage; i++)
    123             {
    124                 /* Any change for this page? */
    125                 if (paPageDesc[i].uHCPhysPageId != NIL_GMM_PAGEID)
    126                 {
    127                     /** todo: maybe cache these to prevent the nth lookup. */
    128                     PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, paPageDesc[i].GCPhys);
    129                     if (!pPage)
    130                     {
    131                         /* Should never happen. */
    132                         AssertFailed();
    133                         rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    134                         goto end;
    135                     }
    136                     Assert(PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED);
    137 
    138                     Log(("PGMR0SharedModuleCheck: shared page gc virt=%RGv phys %RGp host %RHp->%RHp\n", pRegions[idxRegion].GCRegionAddr + i * PAGE_SIZE, paPageDesc[i].GCPhys, PGM_PAGE_GET_HCPHYS(pPage), paPageDesc[i].HCPhys));
    139                     if (paPageDesc[i].HCPhys != PGM_PAGE_GET_HCPHYS(pPage))
    140                     {
    141                         bool fFlush = false;
    142 
    143                         /* Page was replaced by an existing shared version of it; clear all references first. */
    144                         rc = pgmPoolTrackUpdateGCPhys(pVM, paPageDesc[i].GCPhys, pPage, true /* clear the entries */, &fFlush);
    145                         if (RT_FAILURE(rc))
    146                         {
    147                             AssertRC(rc);
    148                             goto end;
    149                         }
    150                         Assert(rc == VINF_SUCCESS || (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3) && (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_CLEAR_PGM_POOL)));
    151                         if (rc == VINF_SUCCESS)
    152                             fFlushTLBs |= fFlush;
    153 
    154                         /* Update the physical address and page id now. */
    155                         PGM_PAGE_SET_HCPHYS(pPage, paPageDesc[i].HCPhys);
    156                         PGM_PAGE_SET_PAGEID(pPage, paPageDesc[i].uHCPhysPageId);
    157 
    158                         /* Invalidate page map TLB entry for this page too. */
    159                         PGMPhysInvalidatePageMapTLBEntry(pVM, paPageDesc[i].GCPhys);
    160                         pVM->pgm.s.cReusedSharedPages++;
    161                     }
    162                     /* else nothing changed (== this page is now a shared page), so no need to flush anything. */
    163 
    164                     pVM->pgm.s.cSharedPages++;
    165                     pVM->pgm.s.cPrivatePages--;
    166                     PGM_PAGE_SET_STATE(pPage, PGM_PAGE_STATE_SHARED);
    167                 }
    168             }
    169         }
    170         else
    171             rc = VINF_SUCCESS;  /* nothing to do. */
    172129    }
    173130
    174 end:
    175131    pgmUnlock(pVM);
    176132    if (fFlushTLBs)
    177133        PGM_INVL_ALL_VCPU_TLBS(pVM);
    178 
    179     if (paPageDesc)
    180         RTMemFree(paPageDesc);
    181134
    182135    return 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