VirtualBox

Changeset 92170 in vbox for trunk


Ignore:
Timestamp:
Nov 1, 2021 10:06:25 PM (3 years ago)
Author:
vboxsync
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

Location:
trunk
Files:
9 edited

Legend:

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

    r91848 r92170  
    30113011/** NEM init failed because of missing kernel API (\#5). */
    30123012#define VERR_NEM_MISSING_KERNEL_API_5               (-6815)
     3013/** NEM failed to query dirty page bitmap. */
     3014#define VERR_NEM_QUERY_DIRTY_BITMAP_FAILED          (-6816)
    30133015
    30143016/** NEM internal processing error \#0. */
  • trunk/include/VBox/vmm/nem.h

    r92129 r92170  
    6262VMMR3_INT_DECL(void) NEMR3NotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags);
    6363
    64 VMMR3_INT_DECL(int)  NEMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvR3, uint8_t *pu2State);
     64/**
     65 * Checks if dirty page tracking for MMIO2 ranges is supported.
     66 *
     67 * If it is, PGM will not install a physical write access handler for the MMIO2
     68 * region and instead just forward dirty bit queries NEMR3QueryMmio2DirtyBits.
     69 * The enable/disable control of the tracking will be ignored, and PGM will
     70 * always set NEM_NOTIFY_PHYS_MMIO_EX_F_TRACK_DIRTY_PAGES for such ranges.
     71 *
     72 * @retval  true if supported.
     73 * @retval  false if not.
     74 * @param   pVM     The cross context VM structure.
     75 */
     76VMMR3_INT_DECL(bool) NEMR3IsMmio2DirtyPageTrackingSupported(PVM pVM);
     77
     78/**
     79 * Worker for PGMR3PhysMmio2QueryAndResetDirtyBitmap.
     80 *
     81 * @returns VBox status code.
     82 * @param   pVM         The cross context VM structure.
     83 * @param   GCPhys      The address of the MMIO2 range.
     84 * @param   cb          The size of the MMIO2 range.
     85 * @param   uNemRange   The NEM internal range number.
     86 * @param   pvBitmap    The output bitmap.  Must be 8-byte aligned.  Ignored
     87 *                      when @a cbBitmap is zero.
     88 * @param   cbBitmap    The size of the bitmap.  Must be the size of the whole
     89 *                      MMIO2 range, rounded up to the nearest 8 bytes.
     90 *                      When zero only a reset is done.
     91 */
     92VMMR3_INT_DECL(int)  NEMR3PhysMmio2QueryAndResetDirtyBitmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t uNemRange,
     93                                                            void *pvBitmap, size_t cbBitmap);
     94
     95VMMR3_INT_DECL(int)  NEMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvR3,
     96                                                uint8_t *pu2State, uint32_t *puNemRange);
    6597VMMR3_INT_DECL(int)  NEMR3NotifyPhysMmioExMapEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
    66                                                    void *pvRam, void *pvMmio2, uint8_t *pu2State);
     98                                                   void *pvRam, void *pvMmio2, uint8_t *pu2State, uint32_t *puNemRange);
    6799VMMR3_INT_DECL(int)  NEMR3NotifyPhysMmioExMapLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
    68                                                   void *pvRam, void *pvMmio2);
     100                                                  void *pvRam, void *pvMmio2, uint32_t *puNemRange);
    69101VMMR3_INT_DECL(int)  NEMR3NotifyPhysMmioExUnmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
    70102                                                void *pvRam, void *pvMmio2, uint8_t *pu2State);
    71103/** @name Flags for NEMR3NotifyPhysMmioExMap and NEMR3NotifyPhysMmioExUnmap.
    72104 * @{ */
     105/** Set if the range is replacing RAM rather that unused space. */
     106#define NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE               RT_BIT(0)
    73107/** Set if it's MMIO2 being mapped or unmapped. */
    74 #define NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2     RT_BIT(0)
    75 /** Set if the range is replacing RAM rather that unused space. */
    76 #define NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE   RT_BIT(1)
     108#define NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2                 RT_BIT(1)
     109/** Set if MMIO2 and dirty page tracking is configured. */
     110#define NEM_NOTIFY_PHYS_MMIO_EX_F_TRACK_DIRTY_PAGES     RT_BIT(2)
    77111/** @} */
    78112
  • trunk/include/VBox/vmm/vm.h

    r91702 r92170  
    13461346        struct NEM  s;
    13471347#endif
    1348         uint8_t     padding[256];       /* multiple of 64 */
     1348        uint8_t     padding[512];       /* multiple of 64 */
    13491349    } nem;
    13501350
     
    14541454
    14551455    /** Padding for aligning the structure size on a page boundrary. */
    1456     uint8_t         abAlignment2[2008 - sizeof(PVMCPUR3) * VMM_MAX_CPU_COUNT];
     1456    uint8_t         abAlignment2[1752 - sizeof(PVMCPUR3) * VMM_MAX_CPU_COUNT];
    14571457
    14581458    /* ---- end small stuff ---- */
  • trunk/include/VBox/vmm/vm.mac

    r91702 r92170  
    149149    .em                     resb 256
    150150    alignb 64
    151     .nem                    resb 256
     151    .nem                    resb 512
    152152    alignb 64
    153153    .tm                     resb 10112
  • trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h

    r92120 r92170  
    16011601# else
    16021602    RT_NOREF_PV(pVCpu);
     1603    STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRangePage, a);
    16031604    HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE);
     1605    STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRangePage, a);
    16041606    if (SUCCEEDED(hrc))
    16051607# endif
     
    17961798# else
    17971799    /** @todo figure out whether we mess up the state or if it's WHv.   */
     1800    STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRangePage, a);
    17981801    HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE);
     1802    STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRangePage, a);
    17991803    if (SUCCEEDED(hrc))
    18001804# endif
     
    46484652    if (pvMemR3)
    46494653    {
     4654        STAM_REL_PROFILE_START(&pVM->nem.s.StatProfMapGpaRange, a);
    46504655        HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvMemR3, GCPhys, cb,
    46514656                                     WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute | WHvMapGpaRangeFlagWrite);
     4657        STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfMapGpaRange, a);
    46524658        if (SUCCEEDED(hrc))
    46534659            *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;
     
    48134819            }
    48144820#  else
     4821            STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRangePage, a);
    48154822            HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhysDst, X86_PAGE_SIZE);
     4823            STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRangePage, a);
    48164824            if (SUCCEEDED(hrc))
    48174825            {
     
    49084916        if (RT_SUCCESS(rc))
    49094917        {
     4918            STAM_REL_PROFILE_START(&pVM->nem.s.StatProfMapGpaRangePage, a);
    49104919            HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, (void *)pvPage, GCPhysDst, X86_PAGE_SIZE,
    49114920                                         WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute);
     4921            STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfMapGpaRangePage, a);
    49124922            if (SUCCEEDED(hrc))
    49134923            {
     
    49634973
    49644974#elif defined(IN_RING3)
     4975    STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRangePage, a);
    49654976    HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhysDst & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, X86_PAGE_SIZE);
     4977    STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRangePage, a);
    49664978    if (SUCCEEDED(hrc))
    49674979    {
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r92129 r92170  
    5959#include <iprt/system.h>
    6060#include <iprt/utf16.h>
     61
     62#ifndef NTDDI_WIN10_VB /* Present in W10 2004 SDK, quite possibly earlier. */
     63HRESULT WINAPI WHvQueryGpaRangeDirtyBitmap(WHV_PARTITION_HANDLE, WHV_GUEST_PHYSICAL_ADDRESS, UINT64, UINT64 *, UINT32);
     64# define WHvMapGpaRangeFlagTrackDirtyPages      ((WHV_MAP_GPA_RANGE_FLAGS)0x00000008)
     65#endif
    6166
    6267
     
    96101static decltype(WHvUnmapGpaRange) *                 g_pfnWHvUnmapGpaRange;
    97102static decltype(WHvTranslateGva) *                  g_pfnWHvTranslateGva;
     103static decltype(WHvQueryGpaRangeDirtyBitmap) *      g_pfnWHvQueryGpaRangeDirtyBitmap;
    98104#ifndef NEM_WIN_USE_OUR_OWN_RUN_API
    99105static decltype(WHvCreateVirtualProcessor) *        g_pfnWHvCreateVirtualProcessor;
     
    147153    NEM_WIN_IMPORT(0, false, WHvUnmapGpaRange),
    148154    NEM_WIN_IMPORT(0, false, WHvTranslateGva),
     155    NEM_WIN_IMPORT(0, true,  WHvQueryGpaRangeDirtyBitmap),
    149156#ifndef NEM_WIN_USE_OUR_OWN_RUN_API
    150157    NEM_WIN_IMPORT(0, false, WHvCreateVirtualProcessor),
     
    222229# define WHvUnmapGpaRange                           g_pfnWHvUnmapGpaRange
    223230# define WHvTranslateGva                            g_pfnWHvTranslateGva
     231# define WHvQueryGpaRangeDirtyBitmap                g_pfnWHvQueryGpaRangeDirtyBitmap
    224232# define WHvCreateVirtualProcessor                  g_pfnWHvCreateVirtualProcessor
    225233# define WHvDeleteVirtualProcessor                  g_pfnWHvDeleteVirtualProcessor
     
    522530        {
    523531            int rc2 = RTLdrGetSymbol(ahMods[g_aImports[i].idxDll], g_aImports[i].pszName, (void **)g_aImports[i].ppfn);
    524             if (RT_FAILURE(rc2))
     532            if (RT_SUCCESS(rc2))
     533            {
     534                if (g_aImports[i].fOptional)
     535                    LogRel(("NEM:  info: Found optional import %s!%s.\n",
     536                            s_apszDllNames[g_aImports[i].idxDll], g_aImports[i].pszName));
     537            }
     538            else
    525539            {
    526540                *g_aImports[i].ppfn = NULL;
     
    13701384                                       "/NEM/PagesUnmapAll", STAMUNIT_PAGES, "Times we had to unmap all the pages");
    13711385#endif
     1386#ifdef VBOX_WITH_PGM_NEM_MODE
     1387                        STAMR3Register(pVM, &pVM->nem.s.StatProfMapGpaRange, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS,
     1388                                       "/NEM/PagesMapGpaRange", STAMUNIT_TICKS_PER_CALL, "Profiling calls to WHvMapGpaRange for bigger stuff");
     1389                        STAMR3Register(pVM, &pVM->nem.s.StatProfUnmapGpaRange, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS,
     1390                                       "/NEM/PagesUnmapGpaRange", STAMUNIT_TICKS_PER_CALL, "Profiling calls to WHvUnmapGpaRange for bigger stuff");
     1391                        STAMR3Register(pVM, &pVM->nem.s.StatProfQueryGpaRangeDirtyBitmap, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS,
     1392                                       "/NEM/PagesQueryGpaRangeDirtyBitmap", STAMUNIT_TICKS_PER_CALL, "Profiling calls to WHvQueryGpaRangeDirtyBitmap (MMIO2/VRAM)");
     1393#  endif
     1394#  ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
     1395                        STAMR3Register(pVM, &pVM->nem.s.StatProfMapGpaRangePage, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS,
     1396                                       "/NEM/PagesMapGpaRangePage", STAMUNIT_TICKS_PER_CALL, "Profiling calls to WHvMapGpaRange for single pages");
     1397                        STAMR3Register(pVM, &pVM->nem.s.StatProfUnmapGpaRangePage, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS,
     1398                                       "/NEM/PagesUnmapGpaRangePage", STAMUNIT_TICKS_PER_CALL, "Profiling calls to WHvUnmapGpaRange for single pages");
     1399#  endif
    13721400
    13731401                        for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     
    19722000
    19732001
    1974 VMMR3_INT_DECL(int) NEMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvR3, uint8_t *pu2State)
    1975 {
    1976     Log5(("NEMR3NotifyPhysRamRegister: %RGp LB %RGp, pvR3=%p\n", GCPhys, cb, pvR3));
     2002VMMR3_INT_DECL(int) NEMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvR3,
     2003                                               uint8_t *pu2State, uint32_t *puNemRange)
     2004{
     2005    Log5(("NEMR3NotifyPhysRamRegister: %RGp LB %RGp, pvR3=%p pu2State=%p (%d) puNemRange=%p (%d)\n",
     2006          GCPhys, cb, pvR3, pu2State, pu2State, puNemRange, *puNemRange));
     2007
    19772008    *pu2State = UINT8_MAX;
     2009    RT_NOREF(puNemRange);
     2010
    19782011#if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) && defined(VBOX_WITH_PGM_NEM_MODE)
    19792012    if (pvR3)
    19802013    {
     2014        STAM_REL_PROFILE_START(&pVM->nem.s.StatProfMapGpaRange, a);
    19812015        HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvR3, GCPhys, cb,
    19822016                                     WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagWrite | WHvMapGpaRangeFlagExecute);
     2017        STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfMapGpaRange, a);
    19832018        if (SUCCEEDED(hrc))
    19842019            *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;
     
    19872022            LogRel(("NEMR3NotifyPhysRamRegister: GCPhys=%RGp LB %RGp pvR3=%p hrc=%Rhrc (%#x) Last=%#x/%u\n",
    19882023                    GCPhys, cb, pvR3, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     2024            STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPageFailed);
    19892025            return VERR_NEM_MAP_PAGES_FAILED;
    19902026        }
     
    19972033
    19982034
     2035VMMR3_INT_DECL(bool) NEMR3IsMmio2DirtyPageTrackingSupported(PVM pVM)
     2036{
     2037    RT_NOREF(pVM);
     2038    return g_pfnWHvQueryGpaRangeDirtyBitmap != NULL;
     2039}
     2040
     2041
    19992042VMMR3_INT_DECL(int) NEMR3NotifyPhysMmioExMapEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
    2000                                                   void *pvRam, void *pvMmio2, uint8_t *pu2State)
    2001 {
    2002     Log5(("NEMR3NotifyPhysMmioExMapEarly: %RGp LB %RGp fFlags=%#x pvRam=%p pvMmio2=%p pu2State=%p (%d)\n",
    2003           GCPhys, cb, fFlags, pvRam, pvMmio2, pu2State, *pu2State));
     2043                                                  void *pvRam, void *pvMmio2, uint8_t *pu2State, uint32_t *puNemRange)
     2044{
     2045    Log5(("NEMR3NotifyPhysMmioExMapEarly: %RGp LB %RGp fFlags=%#x pvRam=%p pvMmio2=%p pu2State=%p (%d) puNemRange=%p (%#x)\n",
     2046          GCPhys, cb, fFlags, pvRam, pvMmio2, pu2State, *pu2State, puNemRange, puNemRange ? *puNemRange : UINT32_MAX));
     2047    RT_NOREF(puNemRange);
    20042048
    20052049#if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) && defined(VBOX_WITH_PGM_NEM_MODE)
     
    20092053    if (fFlags & NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE)
    20102054    {
     2055        STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRange, a);
    20112056        HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, cb);
     2057        STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRange, a);
    20122058        if (SUCCEEDED(hrc))
    20132059        { /* likely */ }
     
    20192065            LogRel(("NEMR3NotifyPhysMmioExMapEarly: GCPhys=%RGp LB %RGp fFlags=%#x: Unmap -> hrc=%Rhrc (%#x) Last=%#x/%u\n",
    20202066                    GCPhys, cb, fFlags, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     2067            STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPageFailed);
    20212068            return VERR_NEM_UNMAP_PAGES_FAILED;
    20222069        }
     
    20292076    {
    20302077        Assert(fFlags & NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2);
    2031         HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvMmio2, GCPhys, cb,
    2032                                      WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagWrite | WHvMapGpaRangeFlagExecute);
     2078        WHV_MAP_GPA_RANGE_FLAGS fWHvFlags = WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagWrite | WHvMapGpaRangeFlagExecute;
     2079        if ((fFlags & NEM_NOTIFY_PHYS_MMIO_EX_F_TRACK_DIRTY_PAGES) && g_pfnWHvQueryGpaRangeDirtyBitmap)
     2080            fWHvFlags |= WHvMapGpaRangeFlagTrackDirtyPages;
     2081        STAM_REL_PROFILE_START(&pVM->nem.s.StatProfMapGpaRange, a);
     2082        HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvMmio2, GCPhys, cb, fWHvFlags);
     2083        STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfMapGpaRange, a);
    20332084        if (SUCCEEDED(hrc))
    20342085            *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;
    20352086        else
    20362087        {
    2037             LogRel(("NEMR3NotifyPhysMmioExMapEarly: GCPhys=%RGp LB %RGp fFlags=%#x pvMmio2=%p: Map -> hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2038                     GCPhys, cb, fFlags, pvMmio2, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     2088            LogRel(("NEMR3NotifyPhysMmioExMapEarly: GCPhys=%RGp LB %RGp fFlags=%#x pvMmio2=%p fWHvFlags=%#x: Map -> hrc=%Rhrc (%#x) Last=%#x/%u\n",
     2089                    GCPhys, cb, fFlags, pvMmio2, fWHvFlags, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     2090            STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPageFailed);
    20392091            return VERR_NEM_MAP_PAGES_FAILED;
    20402092        }
     
    20562108
    20572109VMMR3_INT_DECL(int) NEMR3NotifyPhysMmioExMapLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
    2058                                                  void *pvRam, void *pvMmio2)
    2059 {
    2060     RT_NOREF(pVM, GCPhys, cb, fFlags, pvRam, pvMmio2);
     2110                                                 void *pvRam, void *pvMmio2, uint32_t *puNemRange)
     2111{
     2112    RT_NOREF(pVM, GCPhys, cb, fFlags, pvRam, pvMmio2, puNemRange);
    20612113    return VINF_SUCCESS;
    20622114}
     
    20782130    if (fFlags & NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2)
    20792131    {
     2132        STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRange, a);
    20802133        HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, cb);
     2134        STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRange, a);
    20812135        if (FAILED(hrc))
    20822136        {
     
    20842138                     GCPhys, cb, fFlags, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    20852139            rc = VERR_NEM_UNMAP_PAGES_FAILED;
     2140            STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPageFailed);
    20862141        }
    20872142    }
     
    20932148    {
    20942149        AssertPtr(pvRam);
     2150        STAM_REL_PROFILE_START(&pVM->nem.s.StatProfMapGpaRange, a);
    20952151        HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvRam, GCPhys, cb,
    20962152                                     WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagWrite | WHvMapGpaRangeFlagExecute);
     2153        STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfMapGpaRange, a);
    20972154        if (SUCCEEDED(hrc))
    20982155        { /* likely */ }
     
    21022159                    GCPhys, cb, pvMmio2, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    21032160            rc = VERR_NEM_MAP_PAGES_FAILED;
     2161            STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPageFailed);
    21042162        }
    21052163        if (pu2State)
     
    21172175#endif
    21182176    return rc;
     2177}
     2178
     2179
     2180VMMR3_INT_DECL(int) NEMR3PhysMmio2QueryAndResetDirtyBitmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t uNemRange,
     2181                                                           void *pvBitmap, size_t cbBitmap)
     2182{
     2183#if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) && defined(VBOX_WITH_PGM_NEM_MODE)
     2184    Assert(VM_IS_NEM_ENABLED(pVM));
     2185    AssertReturn(g_pfnWHvQueryGpaRangeDirtyBitmap, VERR_INTERNAL_ERROR_2);
     2186    Assert(cbBitmap == (uint32_t)cbBitmap);
     2187    RT_NOREF(uNemRange);
     2188
     2189    STAM_REL_PROFILE_START(&pVM->nem.s.StatProfQueryGpaRangeDirtyBitmap, a);
     2190    HRESULT hrc = WHvQueryGpaRangeDirtyBitmap(pVM->nem.s.hPartition, GCPhys, cb, (UINT64 *)pvBitmap, (uint32_t)cbBitmap);
     2191    STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfQueryGpaRangeDirtyBitmap, a);
     2192    if (SUCCEEDED(hrc))
     2193        return VINF_SUCCESS;
     2194
     2195    AssertLogRelMsgFailed(("GCPhys=%RGp LB %RGp pvBitmap=%p LB %#zx hrc=%Rhrc (%#x) Last=%#x/%u\n",
     2196                           GCPhys, cb, pvBitmap, cbBitmap, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     2197    return VERR_NEM_QUERY_DIRTY_BITMAP_FAILED;
     2198
     2199#else
     2200    RT_NOREF(pVM, GCPhys, cb, uNemRange, pvBitmap, cbBitmap);
     2201    AssertFailed();
     2202    return VERR_NOT_IMPLEMENTED;
     2203#endif
    21192204}
    21202205
     
    21712256     */
    21722257    AssertPtrReturn(pvPages, VERR_INVALID_POINTER);
     2258    STAM_REL_PROFILE_START(&pVM->nem.s.StatProfMapGpaRange, a);
    21732259    HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvPages, GCPhys, cb, WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute);
     2260    STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfMapGpaRange, a);
    21742261    if (SUCCEEDED(hrc))
    21752262        *pu2State = NEM_WIN_PAGE_STATE_READABLE;
     
    21782265        LogRel(("nemR3NativeNotifyPhysRomRegisterEarly: GCPhys=%RGp LB %RGp pvPages=%p fFlags=%#x hrc=%Rhrc (%#x) Last=%#x/%u\n",
    21792266                GCPhys, cb, pvPages, fFlags, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     2267        STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPageFailed);
    21802268        return VERR_NEM_MAP_PAGES_FAILED;
    21812269    }
     
    21872275}
    21882276
     2277#ifdef NEM_WIN_WITH_A20
    21892278
    21902279/**
     
    22292318
    22302319
    2231 #ifdef NEM_WIN_WITH_A20
    22322320/**
    22332321 * Unmaps a page from Hyper-V for the purpose of emulating A20 gate behavior.
     
    22442332                                     nemR3WinUnsetForA20CheckerCallback, NULL);
    22452333}
    2246 #endif
    2247 
     2334
     2335#endif /* NEM_WIN_WITH_A20 */
    22482336
    22492337/**
  • 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    /*
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r92120 r92170  
    217217    STAMCOUNTER                 StatMapPageFailed;
    218218    STAMCOUNTER                 StatUnmapPageFailed;
     219#  ifdef VBOX_WITH_PGM_NEM_MODE
     220    STAMPROFILE                 StatProfMapGpaRange;
     221    STAMPROFILE                 StatProfUnmapGpaRange;
     222    STAMPROFILE                 StatProfQueryGpaRangeDirtyBitmap;
     223#  endif
     224#  ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
     225    STAMPROFILE                 StatProfMapGpaRangePage;
     226    STAMPROFILE                 StatProfUnmapGpaRangePage;
     227#  endif
    219228
    220229#  ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
  • trunk/src/VBox/VMM/include/PGMInternal.h

    r92162 r92170  
    11791179    /** PGM_RAM_RANGE_FLAGS_* flags. */
    11801180    uint32_t                            fFlags;
    1181     uint32_t                            fPadding1;
     1181    /** NEM specific info, UINT32_MAX if not used. */
     1182    uint32_t                            uNemRange;
    11821183    /** Last address in the range (inclusive). Page aligned (-1). */
    11831184    RTGCPHYS                            GCPhysLast;
     
    14211422     * reduced during saved state loading. */
    14221423    RTGCPHYS                            cbReal;
    1423     /** Pointer to the physical handler for MMIO. */
     1424    /** Pointer to the physical handler for MMIO.
     1425     * If NEM is responsible for tracking dirty pages in simple memory mode, this
     1426     * will be NULL. */
    14241427    R3PTRTYPE(PPGMPHYSHANDLER)          pPhysHandlerR3;
    14251428    /** Live save per page tracking data for MMIO2. */
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