- Timestamp:
- Nov 1, 2021 10:06:25 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/err.h
r91848 r92170 3011 3011 /** NEM init failed because of missing kernel API (\#5). */ 3012 3012 #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) 3013 3015 3014 3016 /** NEM internal processing error \#0. */ -
trunk/include/VBox/vmm/nem.h
r92129 r92170 62 62 VMMR3_INT_DECL(void) NEMR3NotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags); 63 63 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 */ 76 VMMR3_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 */ 92 VMMR3_INT_DECL(int) NEMR3PhysMmio2QueryAndResetDirtyBitmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t uNemRange, 93 void *pvBitmap, size_t cbBitmap); 94 95 VMMR3_INT_DECL(int) NEMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvR3, 96 uint8_t *pu2State, uint32_t *puNemRange); 65 97 VMMR3_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); 67 99 VMMR3_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); 69 101 VMMR3_INT_DECL(int) NEMR3NotifyPhysMmioExUnmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags, 70 102 void *pvRam, void *pvMmio2, uint8_t *pu2State); 71 103 /** @name Flags for NEMR3NotifyPhysMmioExMap and NEMR3NotifyPhysMmioExUnmap. 72 104 * @{ */ 105 /** Set if the range is replacing RAM rather that unused space. */ 106 #define NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE RT_BIT(0) 73 107 /** 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) 77 111 /** @} */ 78 112 -
trunk/include/VBox/vmm/vm.h
r91702 r92170 1346 1346 struct NEM s; 1347 1347 #endif 1348 uint8_t padding[ 256]; /* multiple of 64 */1348 uint8_t padding[512]; /* multiple of 64 */ 1349 1349 } nem; 1350 1350 … … 1454 1454 1455 1455 /** 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]; 1457 1457 1458 1458 /* ---- end small stuff ---- */ -
trunk/include/VBox/vmm/vm.mac
r91702 r92170 149 149 .em resb 256 150 150 alignb 64 151 .nem resb 256151 .nem resb 512 152 152 alignb 64 153 153 .tm resb 10112 -
trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h
r92120 r92170 1601 1601 # else 1602 1602 RT_NOREF_PV(pVCpu); 1603 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRangePage, a); 1603 1604 HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE); 1605 STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRangePage, a); 1604 1606 if (SUCCEEDED(hrc)) 1605 1607 # endif … … 1796 1798 # else 1797 1799 /** @todo figure out whether we mess up the state or if it's WHv. */ 1800 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRangePage, a); 1798 1801 HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE); 1802 STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRangePage, a); 1799 1803 if (SUCCEEDED(hrc)) 1800 1804 # endif … … 4648 4652 if (pvMemR3) 4649 4653 { 4654 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfMapGpaRange, a); 4650 4655 HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvMemR3, GCPhys, cb, 4651 4656 WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute | WHvMapGpaRangeFlagWrite); 4657 STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfMapGpaRange, a); 4652 4658 if (SUCCEEDED(hrc)) 4653 4659 *pu2State = NEM_WIN_PAGE_STATE_WRITABLE; … … 4813 4819 } 4814 4820 # else 4821 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRangePage, a); 4815 4822 HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhysDst, X86_PAGE_SIZE); 4823 STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRangePage, a); 4816 4824 if (SUCCEEDED(hrc)) 4817 4825 { … … 4908 4916 if (RT_SUCCESS(rc)) 4909 4917 { 4918 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfMapGpaRangePage, a); 4910 4919 HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, (void *)pvPage, GCPhysDst, X86_PAGE_SIZE, 4911 4920 WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute); 4921 STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfMapGpaRangePage, a); 4912 4922 if (SUCCEEDED(hrc)) 4913 4923 { … … 4963 4973 4964 4974 #elif defined(IN_RING3) 4975 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRangePage, a); 4965 4976 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); 4966 4978 if (SUCCEEDED(hrc)) 4967 4979 { -
trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp
r92129 r92170 59 59 #include <iprt/system.h> 60 60 #include <iprt/utf16.h> 61 62 #ifndef NTDDI_WIN10_VB /* Present in W10 2004 SDK, quite possibly earlier. */ 63 HRESULT WINAPI WHvQueryGpaRangeDirtyBitmap(WHV_PARTITION_HANDLE, WHV_GUEST_PHYSICAL_ADDRESS, UINT64, UINT64 *, UINT32); 64 # define WHvMapGpaRangeFlagTrackDirtyPages ((WHV_MAP_GPA_RANGE_FLAGS)0x00000008) 65 #endif 61 66 62 67 … … 96 101 static decltype(WHvUnmapGpaRange) * g_pfnWHvUnmapGpaRange; 97 102 static decltype(WHvTranslateGva) * g_pfnWHvTranslateGva; 103 static decltype(WHvQueryGpaRangeDirtyBitmap) * g_pfnWHvQueryGpaRangeDirtyBitmap; 98 104 #ifndef NEM_WIN_USE_OUR_OWN_RUN_API 99 105 static decltype(WHvCreateVirtualProcessor) * g_pfnWHvCreateVirtualProcessor; … … 147 153 NEM_WIN_IMPORT(0, false, WHvUnmapGpaRange), 148 154 NEM_WIN_IMPORT(0, false, WHvTranslateGva), 155 NEM_WIN_IMPORT(0, true, WHvQueryGpaRangeDirtyBitmap), 149 156 #ifndef NEM_WIN_USE_OUR_OWN_RUN_API 150 157 NEM_WIN_IMPORT(0, false, WHvCreateVirtualProcessor), … … 222 229 # define WHvUnmapGpaRange g_pfnWHvUnmapGpaRange 223 230 # define WHvTranslateGva g_pfnWHvTranslateGva 231 # define WHvQueryGpaRangeDirtyBitmap g_pfnWHvQueryGpaRangeDirtyBitmap 224 232 # define WHvCreateVirtualProcessor g_pfnWHvCreateVirtualProcessor 225 233 # define WHvDeleteVirtualProcessor g_pfnWHvDeleteVirtualProcessor … … 522 530 { 523 531 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 525 539 { 526 540 *g_aImports[i].ppfn = NULL; … … 1370 1384 "/NEM/PagesUnmapAll", STAMUNIT_PAGES, "Times we had to unmap all the pages"); 1371 1385 #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 1372 1400 1373 1401 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++) … … 1972 2000 1973 2001 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)); 2002 VMMR3_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 1977 2008 *pu2State = UINT8_MAX; 2009 RT_NOREF(puNemRange); 2010 1978 2011 #if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) && defined(VBOX_WITH_PGM_NEM_MODE) 1979 2012 if (pvR3) 1980 2013 { 2014 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfMapGpaRange, a); 1981 2015 HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvR3, GCPhys, cb, 1982 2016 WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagWrite | WHvMapGpaRangeFlagExecute); 2017 STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfMapGpaRange, a); 1983 2018 if (SUCCEEDED(hrc)) 1984 2019 *pu2State = NEM_WIN_PAGE_STATE_WRITABLE; … … 1987 2022 LogRel(("NEMR3NotifyPhysRamRegister: GCPhys=%RGp LB %RGp pvR3=%p hrc=%Rhrc (%#x) Last=%#x/%u\n", 1988 2023 GCPhys, cb, pvR3, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 2024 STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPageFailed); 1989 2025 return VERR_NEM_MAP_PAGES_FAILED; 1990 2026 } … … 1997 2033 1998 2034 2035 VMMR3_INT_DECL(bool) NEMR3IsMmio2DirtyPageTrackingSupported(PVM pVM) 2036 { 2037 RT_NOREF(pVM); 2038 return g_pfnWHvQueryGpaRangeDirtyBitmap != NULL; 2039 } 2040 2041 1999 2042 VMMR3_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); 2004 2048 2005 2049 #if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) && defined(VBOX_WITH_PGM_NEM_MODE) … … 2009 2053 if (fFlags & NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE) 2010 2054 { 2055 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRange, a); 2011 2056 HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, cb); 2057 STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRange, a); 2012 2058 if (SUCCEEDED(hrc)) 2013 2059 { /* likely */ } … … 2019 2065 LogRel(("NEMR3NotifyPhysMmioExMapEarly: GCPhys=%RGp LB %RGp fFlags=%#x: Unmap -> hrc=%Rhrc (%#x) Last=%#x/%u\n", 2020 2066 GCPhys, cb, fFlags, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 2067 STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPageFailed); 2021 2068 return VERR_NEM_UNMAP_PAGES_FAILED; 2022 2069 } … … 2029 2076 { 2030 2077 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); 2033 2084 if (SUCCEEDED(hrc)) 2034 2085 *pu2State = NEM_WIN_PAGE_STATE_WRITABLE; 2035 2086 else 2036 2087 { 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); 2039 2091 return VERR_NEM_MAP_PAGES_FAILED; 2040 2092 } … … 2056 2108 2057 2109 VMMR3_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); 2061 2113 return VINF_SUCCESS; 2062 2114 } … … 2078 2130 if (fFlags & NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2) 2079 2131 { 2132 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRange, a); 2080 2133 HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, cb); 2134 STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRange, a); 2081 2135 if (FAILED(hrc)) 2082 2136 { … … 2084 2138 GCPhys, cb, fFlags, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 2085 2139 rc = VERR_NEM_UNMAP_PAGES_FAILED; 2140 STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPageFailed); 2086 2141 } 2087 2142 } … … 2093 2148 { 2094 2149 AssertPtr(pvRam); 2150 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfMapGpaRange, a); 2095 2151 HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvRam, GCPhys, cb, 2096 2152 WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagWrite | WHvMapGpaRangeFlagExecute); 2153 STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfMapGpaRange, a); 2097 2154 if (SUCCEEDED(hrc)) 2098 2155 { /* likely */ } … … 2102 2159 GCPhys, cb, pvMmio2, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 2103 2160 rc = VERR_NEM_MAP_PAGES_FAILED; 2161 STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPageFailed); 2104 2162 } 2105 2163 if (pu2State) … … 2117 2175 #endif 2118 2176 return rc; 2177 } 2178 2179 2180 VMMR3_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 2119 2204 } 2120 2205 … … 2171 2256 */ 2172 2257 AssertPtrReturn(pvPages, VERR_INVALID_POINTER); 2258 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfMapGpaRange, a); 2173 2259 HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvPages, GCPhys, cb, WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute); 2260 STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfMapGpaRange, a); 2174 2261 if (SUCCEEDED(hrc)) 2175 2262 *pu2State = NEM_WIN_PAGE_STATE_READABLE; … … 2178 2265 LogRel(("nemR3NativeNotifyPhysRomRegisterEarly: GCPhys=%RGp LB %RGp pvPages=%p fFlags=%#x hrc=%Rhrc (%#x) Last=%#x/%u\n", 2179 2266 GCPhys, cb, pvPages, fFlags, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 2267 STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPageFailed); 2180 2268 return VERR_NEM_MAP_PAGES_FAILED; 2181 2269 } … … 2187 2275 } 2188 2276 2277 #ifdef NEM_WIN_WITH_A20 2189 2278 2190 2279 /** … … 2229 2318 2230 2319 2231 #ifdef NEM_WIN_WITH_A202232 2320 /** 2233 2321 * Unmaps a page from Hyper-V for the purpose of emulating A20 gate behavior. … … 2244 2332 nemR3WinUnsetForA20CheckerCallback, NULL); 2245 2333 } 2246 #endif 2247 2334 2335 #endif /* NEM_WIN_WITH_A20 */ 2248 2336 2249 2337 /** -
trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp
r92167 r92170 1504 1504 int rc = NEMR3NotifyPhysMmioExMapEarly(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemNotify, 1505 1505 pRam->pvR3 ? (uint8_t *)pRam->pvR3 + GCPhys - pRam->GCPhys : NULL, 1506 pvMmio2, &u2State );1506 pvMmio2, &u2State, NULL /*puNemRange*/); 1507 1507 AssertLogRelRCReturn(rc, rc); 1508 1508 … … 1542 1542 { 1543 1543 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*/); 1545 1546 AssertLogRelRCReturnStmt(rc, GMMR3FreePagesCleanup(pReq), rc); 1546 1547 } … … 1605 1606 pNew->pszDesc = pszDesc; 1606 1607 pNew->fFlags = fFlags; 1608 pNew->uNemRange = UINT32_MAX; 1607 1609 pNew->pvR3 = NULL; 1608 1610 pNew->paLSPages = NULL; … … 1651 1653 { 1652 1654 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); 1654 1656 if (RT_SUCCESS(rc)) 1655 1657 { … … 2363 2365 if (VM_IS_NEM_ENABLED(pVM)) 2364 2366 { 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); 2366 2369 AssertLogRelRCReturnStmt(rc, MMHyperFree(pVM, pNew), rc); 2367 2370 } … … 2409 2412 rc = NEMR3NotifyPhysMmioExMapLate(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemNotify, 2410 2413 fRamExists ? (uint8_t *)pRam->pvR3 + (uintptr_t)(GCPhys - pRam->GCPhys) : NULL, 2411 NULL );2414 NULL, !fRamExists ? &pRam->uNemRange : NULL); 2412 2415 AssertLogRelRCReturn(rc, rc); 2413 2416 } … … 2844 2847 pNew->RamRange.cb = pNew->cbReal = (RTGCPHYS)cPagesTrackedByChunk << X86_PAGE_SHIFT; 2845 2848 pNew->RamRange.fFlags |= PGM_RAM_RANGE_FLAGS_AD_HOC_MMIO_EX; 2849 pNew->RamRange.uNemRange = UINT32_MAX; 2846 2850 //pNew->RamRange.pvR3 = NULL; 2847 2851 //pNew->RamRange.paLSPages = NULL; … … 2853 2857 2854 2858 /* 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. 2856 2860 */ 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 2858 2867 { 2859 2868 rc = pgmHandlerPhysicalExCreate(pVM, pVM->pgm.s.hMmio2DirtyPhysHandlerType, … … 3462 3471 int rc = NEMR3NotifyPhysMmioExMapEarly(pVM, pCurMmio->RamRange.GCPhys, 3463 3472 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); 3466 3478 AssertLogRelRCReturnStmt(rc, PGM_UNLOCK(pVM), rc); 3467 3479 } … … 3529 3541 int rc; 3530 3542 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; 3531 3545 if (fRamExists) 3532 3546 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*/); 3534 3549 else 3535 3550 { … … 3538 3553 { 3539 3554 rc = NEMR3NotifyPhysMmioExMapLate(pVM, pCurMmio->RamRange.GCPhys, pCurMmio->RamRange.cb, fNemFlags, 3540 NULL, pCurMmio->RamRange.pvR3 );3555 NULL, pCurMmio->RamRange.pvR3, &pCurMmio->RamRange.uNemRange); 3541 3556 if ((pCurMmio->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK) || RT_FAILURE(rc)) 3542 3557 break; … … 3614 3629 int rcRet = VINF_SUCCESS; 3615 3630 #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); 3617 3634 #endif 3618 3635 if (fOldFlags & PGMREGMMIO2RANGE_F_OVERLAPPING) … … 3757 3774 ("%s: %#x\n", pFirstMmio->RamRange.pszDesc, pFirstMmio->fFlags), 3758 3775 rc = VERR_NOT_SUPPORTED); 3759 3760 #ifdef VBOX_WITH_PGM_NEM_MODE3761 /*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 #endif3769 3776 if (RT_SUCCESS(rc)) 3770 3777 { … … 3867 3874 for (PPGMREGMMIO2RANGE pCur = pFirstRegMmio;;) 3868 3875 { 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. */ 3870 3877 fTotalDirty |= pCur->fFlags; 3871 3878 if (pCur->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK) … … 3892 3899 if (pvBitmap) 3893 3900 { 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 3894 3921 if (fTotalDirty & PGMREGMMIO2RANGE_F_IS_DIRTY) 3895 3922 { … … 3949 3976 else if ( (pFirstRegMmio->fFlags & (PGMREGMMIO2RANGE_F_MAPPED | PGMREGMMIO2RANGE_F_TRACKING_ENABLED)) 3950 3977 == (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 } 3952 4007 3953 4008 return rc; … … 4006 4061 , VERR_INVALID_FUNCTION); 4007 4062 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 4008 4075 4009 4076 /* -
trunk/src/VBox/VMM/include/NEMInternal.h
r92120 r92170 217 217 STAMCOUNTER StatMapPageFailed; 218 218 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 219 228 220 229 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES -
trunk/src/VBox/VMM/include/PGMInternal.h
r92162 r92170 1179 1179 /** PGM_RAM_RANGE_FLAGS_* flags. */ 1180 1180 uint32_t fFlags; 1181 uint32_t fPadding1; 1181 /** NEM specific info, UINT32_MAX if not used. */ 1182 uint32_t uNemRange; 1182 1183 /** Last address in the range (inclusive). Page aligned (-1). */ 1183 1184 RTGCPHYS GCPhysLast; … … 1421 1422 * reduced during saved state loading. */ 1422 1423 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. */ 1424 1427 R3PTRTYPE(PPGMPHYSHANDLER) pPhysHandlerR3; 1425 1428 /** Live save per page tracking data for MMIO2. */
Note:
See TracChangeset
for help on using the changeset viewer.