VirtualBox

Ignore:
Timestamp:
Nov 1, 2021 10:06:25 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
147993
Message:

VMM/PGM,NEM: Let NEM handle dirty VRAM (MMIO2) page tracking. Saves lots of exits when using the VBoxVGA device or VMSVGA in non-VMSVGA mode. Added a 32-bit NEM field to the PGMRAMRANGE structure called uNemRange. bugref:10122

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp

    r92167 r92170  
    15041504        int rc = NEMR3NotifyPhysMmioExMapEarly(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemNotify,
    15051505                                               pRam->pvR3 ? (uint8_t *)pRam->pvR3 + GCPhys - pRam->GCPhys : NULL,
    1506                                                pvMmio2, &u2State);
     1506                                               pvMmio2, &u2State, NULL /*puNemRange*/);
    15071507        AssertLogRelRCReturn(rc, rc);
    15081508
     
    15421542    {
    15431543        uint32_t const fNemNotify = (pvMmio2 ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0) | NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE;
    1544         rc = NEMR3NotifyPhysMmioExMapEarly(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemNotify, NULL, pvMmio2, &u2State);
     1544        rc = NEMR3NotifyPhysMmioExMapEarly(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemNotify, NULL, pvMmio2,
     1545                                           &u2State, NULL /*puNemRange*/);
    15451546        AssertLogRelRCReturnStmt(rc, GMMR3FreePagesCleanup(pReq), rc);
    15461547    }
     
    16051606    pNew->pszDesc       = pszDesc;
    16061607    pNew->fFlags        = fFlags;
     1608    pNew->uNemRange     = UINT32_MAX;
    16071609    pNew->pvR3          = NULL;
    16081610    pNew->paLSPages     = NULL;
     
    16511653    {
    16521654        uint8_t u2State = UINT8_MAX;
    1653         int rc = NEMR3NotifyPhysRamRegister(pVM, GCPhys, pNew->cb, pNew->pvR3, &u2State);
     1655        int rc = NEMR3NotifyPhysRamRegister(pVM, GCPhys, pNew->cb, pNew->pvR3, &u2State, &pNew->uNemRange);
    16541656        if (RT_SUCCESS(rc))
    16551657        {
     
    23632365        if (VM_IS_NEM_ENABLED(pVM))
    23642366        {
    2365             rc = NEMR3NotifyPhysMmioExMapEarly(pVM, GCPhys, cPages << PAGE_SHIFT, 0 /*fFlags*/, NULL, NULL, &u2State);
     2367            rc = NEMR3NotifyPhysMmioExMapEarly(pVM, GCPhys, cPages << PAGE_SHIFT, 0 /*fFlags*/, NULL, NULL,
     2368                                               &u2State, &pNew->uNemRange);
    23662369            AssertLogRelRCReturnStmt(rc, MMHyperFree(pVM, pNew), rc);
    23672370        }
     
    24092412            rc = NEMR3NotifyPhysMmioExMapLate(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemNotify,
    24102413                                              fRamExists ? (uint8_t *)pRam->pvR3 + (uintptr_t)(GCPhys - pRam->GCPhys) : NULL,
    2411                                               NULL);
     2414                                              NULL, !fRamExists ? &pRam->uNemRange : NULL);
    24122415            AssertLogRelRCReturn(rc, rc);
    24132416        }
     
    28442847        pNew->RamRange.cb           = pNew->cbReal = (RTGCPHYS)cPagesTrackedByChunk << X86_PAGE_SHIFT;
    28452848        pNew->RamRange.fFlags      |= PGM_RAM_RANGE_FLAGS_AD_HOC_MMIO_EX;
     2849        pNew->RamRange.uNemRange    = UINT32_MAX;
    28462850        //pNew->RamRange.pvR3       = NULL;
    28472851        //pNew->RamRange.paLSPages  = NULL;
     
    28532857
    28542858        /*
    2855          * Pre-allocate a handler if we're tracking dirty pages.
     2859         * Pre-allocate a handler if we're tracking dirty pages, unless NEM takes care of this.
    28562860         */
    2857         if (fFlags & PGMPHYS_MMIO2_FLAGS_TRACK_DIRTY_PAGES)
     2861        if (   (fFlags & PGMPHYS_MMIO2_FLAGS_TRACK_DIRTY_PAGES)
     2862#ifdef VBOX_WITH_PGM_NEM_MODE
     2863            && !NEMR3IsMmio2DirtyPageTrackingSupported(pVM)
     2864#endif
     2865            )
     2866
    28582867        {
    28592868            rc = pgmHandlerPhysicalExCreate(pVM, pVM->pgm.s.hMmio2DirtyPhysHandlerType,
     
    34623471                int rc = NEMR3NotifyPhysMmioExMapEarly(pVM, pCurMmio->RamRange.GCPhys,
    34633472                                                       pCurMmio->RamRange.GCPhysLast - pCurMmio->RamRange.GCPhys + 1,
    3464                                                        NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2,
    3465                                                        NULL /*pvRam*/, pCurMmio->RamRange.pvR3, &u2NemState);
     3473                                                       NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2
     3474                                                       | (pCurMmio->fFlags & PGMREGMMIO2RANGE_F_TRACK_DIRTY_PAGES
     3475                                                          ? NEM_NOTIFY_PHYS_MMIO_EX_F_TRACK_DIRTY_PAGES : 0),
     3476                                                       NULL /*pvRam*/, pCurMmio->RamRange.pvR3,
     3477                                                       &u2NemState, &pCurMmio->RamRange.uNemRange);
    34663478                AssertLogRelRCReturnStmt(rc, PGM_UNLOCK(pVM), rc);
    34673479            }
     
    35293541        int rc;
    35303542        uint32_t fNemFlags = NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2;
     3543        if (pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_TRACK_DIRTY_PAGES)
     3544            fNemFlags |= NEM_NOTIFY_PHYS_MMIO_EX_F_TRACK_DIRTY_PAGES;
    35313545        if (fRamExists)
    35323546            rc = NEMR3NotifyPhysMmioExMapLate(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemFlags | NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE,
    3533                                               pRam->pvR3 ? (uint8_t *)pRam->pvR3 + GCPhys - pRam->GCPhys : NULL, pFirstMmio->pvR3);
     3547                                              pRam->pvR3 ? (uint8_t *)pRam->pvR3 + GCPhys - pRam->GCPhys : NULL, pFirstMmio->pvR3,
     3548                                              NULL /*puNemRange*/);
    35343549        else
    35353550        {
     
    35383553            {
    35393554                rc = NEMR3NotifyPhysMmioExMapLate(pVM, pCurMmio->RamRange.GCPhys, pCurMmio->RamRange.cb, fNemFlags,
    3540                                                   NULL, pCurMmio->RamRange.pvR3);
     3555                                                  NULL, pCurMmio->RamRange.pvR3, &pCurMmio->RamRange.uNemRange);
    35413556                if ((pCurMmio->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK) || RT_FAILURE(rc))
    35423557                    break;
     
    36143629    int            rcRet     = VINF_SUCCESS;
    36153630#ifdef VBOX_WITH_NATIVE_NEM
    3616     uint32_t const fNemFlags = NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2;
     3631    uint32_t const fNemFlags = NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2
     3632                             | (fOldFlags & PGMREGMMIO2RANGE_F_TRACK_DIRTY_PAGES
     3633                                ? NEM_NOTIFY_PHYS_MMIO_EX_F_TRACK_DIRTY_PAGES : 0);
    36173634#endif
    36183635    if (fOldFlags & PGMREGMMIO2RANGE_F_OVERLAPPING)
     
    37573774                                ("%s: %#x\n", pFirstMmio->RamRange.pszDesc, pFirstMmio->fFlags),
    37583775                                rc = VERR_NOT_SUPPORTED);
    3759 
    3760 #ifdef VBOX_WITH_PGM_NEM_MODE
    3761             /*
    3762              * Currently not supported for NEM in simple memory mode.
    3763              */
    3764             /** @todo implement this for NEM. */
    3765             if (RT_SUCCESS(rc))
    3766                 AssertLogRelMsgStmt(VM_IS_NEM_ENABLED(pVM), ("%s: %#x\n", pFirstMmio->RamRange.pszDesc),
    3767                                     rc = VERR_PGM_NOT_SUPPORTED_FOR_NEM_MODE);
    3768 #endif
    37693776            if (RT_SUCCESS(rc))
    37703777            {
     
    38673874    for (PPGMREGMMIO2RANGE pCur = pFirstRegMmio;;)
    38683875    {
    3869         cbTotal     += pCur->cbReal; /** @todo good question for NEM... */
     3876        cbTotal     += pCur->RamRange.cb; /* Not using cbReal here, because NEM is not in on the creating, only the mapping. */
    38703877        fTotalDirty |= pCur->fFlags;
    38713878        if (pCur->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK)
     
    38923899    if (pvBitmap)
    38933900    {
     3901#ifdef VBOX_WITH_PGM_NEM_MODE
     3902        if (pFirstRegMmio->pPhysHandlerR3 == NULL)
     3903        {
     3904            AssertReturn(VM_IS_NEM_ENABLED(pVM), VERR_INTERNAL_ERROR_4);
     3905            uint8_t *pbBitmap = (uint8_t *)pvBitmap;
     3906            for (PPGMREGMMIO2RANGE pCur = pFirstRegMmio; pCur; pCur = pCur->pNextR3)
     3907            {
     3908                size_t const cbBitmapChunk = pCur->RamRange.cb / PAGE_SIZE / 8;
     3909                Assert((RTGCPHYS)cbBitmapChunk * PAGE_SIZE * 8 == pCur->RamRange.cb);
     3910                int rc2 = NEMR3PhysMmio2QueryAndResetDirtyBitmap(pVM, pCur->RamRange.GCPhys, pCur->RamRange.cb,
     3911                                                                 pCur->RamRange.uNemRange, pbBitmap, cbBitmapChunk);
     3912                if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     3913                    rc = rc2;
     3914                if (pCur->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK)
     3915                    break;
     3916                pbBitmap += pCur->RamRange.cb / PAGE_SIZE / 8;
     3917            }
     3918        }
     3919        else
     3920#endif
    38943921        if (fTotalDirty & PGMREGMMIO2RANGE_F_IS_DIRTY)
    38953922        {
     
    39493976    else if (   (pFirstRegMmio->fFlags & (PGMREGMMIO2RANGE_F_MAPPED | PGMREGMMIO2RANGE_F_TRACKING_ENABLED))
    39503977             ==                          (PGMREGMMIO2RANGE_F_MAPPED | PGMREGMMIO2RANGE_F_TRACKING_ENABLED))
    3951         rc = PGMHandlerPhysicalReset(pVM, pFirstRegMmio->RamRange.GCPhys);
     3978    {
     3979#ifdef VBOX_WITH_PGM_NEM_MODE
     3980        if (pFirstRegMmio->pPhysHandlerR3 == NULL)
     3981        {
     3982            AssertReturn(VM_IS_NEM_ENABLED(pVM), VERR_INTERNAL_ERROR_4);
     3983            for (PPGMREGMMIO2RANGE pCur = pFirstRegMmio; pCur; pCur = pCur->pNextR3)
     3984            {
     3985                int rc2 = NEMR3PhysMmio2QueryAndResetDirtyBitmap(pVM, pCur->RamRange.GCPhys, pCur->RamRange.cb,
     3986                                                                 pCur->RamRange.uNemRange, NULL, 0);
     3987                if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     3988                    rc = rc2;
     3989                if (pCur->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK)
     3990                    break;
     3991            }
     3992        }
     3993        else
     3994#endif
     3995        {
     3996            for (PPGMREGMMIO2RANGE pCur = pFirstRegMmio; pCur; pCur = pCur->pNextR3)
     3997            {
     3998                pCur->fFlags &= ~PGMREGMMIO2RANGE_F_IS_DIRTY;
     3999                int rc2 = PGMHandlerPhysicalReset(pVM, pCur->RamRange.GCPhys);
     4000                if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     4001                    rc = rc2;
     4002                if (pCur->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK)
     4003                    break;
     4004            }
     4005        }
     4006    }
    39524007
    39534008    return rc;
     
    40064061                 , VERR_INVALID_FUNCTION);
    40074062    AssertReturn(pDevIns == pFirstRegMmio->pDevInsR3, VERR_NOT_OWNER);
     4063
     4064#ifdef VBOX_WITH_PGM_NEM_MODE
     4065    /*
     4066     * This is a nop if NEM is responsible for doing the tracking, we simply
     4067     * leave the tracking on all the time there.
     4068     */
     4069    if (pFirstRegMmio->pPhysHandlerR3 == NULL)
     4070    {
     4071        AssertReturn(VM_IS_NEM_ENABLED(pVM), VERR_INTERNAL_ERROR_4);
     4072        return VINF_SUCCESS;
     4073    }
     4074#endif
    40084075
    40094076    /*
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