Changeset 91848 in vbox for trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp
- Timestamp:
- Oct 19, 2021 11:18:13 PM (3 years ago)
- svn:sync-xref-src-repo-rev:
- 147650
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp
r91732 r91848 1158 1158 * @param GCPhys The address of the first page. 1159 1159 * @param GCPhysLast The address of the last page. 1160 * @param enmType The page type to replace then with. 1161 */ 1162 static int pgmR3PhysFreePageRange(PVM pVM, PPGMRAMRANGE pRam, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast, PGMPAGETYPE enmType) 1160 * @param pvMmio2 Pointer to the ring-3 mapping of any MMIO2 memory that 1161 * will replace the pages we're freeing up. 1162 */ 1163 static int pgmR3PhysFreePageRange(PVM pVM, PPGMRAMRANGE pRam, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast, void *pvMmio2) 1163 1164 { 1164 1165 PGM_LOCK_ASSERT_OWNER(pVM); 1166 1167 #ifdef VBOX_WITH_PGM_NEM_MODE 1168 /* 1169 * In simplified memory mode we don't actually free the memory, 1170 * we just unmap it and let NEM do any unlocking of it. 1171 */ 1172 if (pVM->pgm.s.fNemMode) 1173 { 1174 Assert(VM_IS_NEM_ENABLED(pVM)); 1175 uint32_t const fNemNotify = (pvMmio2 ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0) | NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE; 1176 uint8_t u2State = 0; /* (We don't support UINT8_MAX here.) */ 1177 int rc = NEMR3NotifyPhysMmioExMapEarly(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemNotify, 1178 pRam->pvR3 ? (uint8_t *)pRam->pvR3 + GCPhys - pRam->GCPhys : NULL, 1179 pvMmio2, &u2State); 1180 AssertLogRelRCReturn(rc, rc); 1181 1182 /* Iterate the pages. */ 1183 PPGMPAGE pPageDst = &pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT]; 1184 uint32_t cPagesLeft = ((GCPhysLast - GCPhys) >> PAGE_SHIFT) + 1; 1185 while (cPagesLeft-- > 0) 1186 { 1187 rc = pgmPhysFreePage(pVM, NULL, NULL, pPageDst, GCPhys, PGMPAGETYPE_MMIO); 1188 AssertLogRelRCReturn(rc, rc); /* We're done for if this goes wrong. */ 1189 1190 PGM_PAGE_SET_TYPE(pVM, pPageDst, PGMPAGETYPE_MMIO); 1191 PGM_PAGE_SET_NEM_STATE(pPageDst, u2State); 1192 1193 GCPhys += PAGE_SIZE; 1194 pPageDst++; 1195 } 1196 return rc; 1197 } 1198 #endif /* VBOX_WITH_PGM_NEM_MODE */ 1199 1200 /* 1201 * Regular mode. 1202 */ 1203 /* Prepare. */ 1165 1204 uint32_t cPendingPages = 0; 1166 1205 PGMMFREEPAGESREQ pReq; … … 1168 1207 AssertLogRelRCReturn(rc, rc); 1169 1208 1209 #ifdef VBOX_WITH_NATIVE_NEM 1210 /* Tell NEM up-front. */ 1211 uint8_t u2State = UINT8_MAX; 1212 if (VM_IS_NEM_ENABLED(pVM)) 1213 { 1214 uint32_t const fNemNotify = (pvMmio2 ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0) | NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE; 1215 rc = NEMR3NotifyPhysMmioExMapEarly(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemNotify, NULL, pvMmio2, &u2State); 1216 AssertLogRelRCReturnStmt(rc, GMMR3FreePagesCleanup(pReq), rc); 1217 } 1218 #endif 1219 1170 1220 /* Iterate the pages. */ 1171 1221 PPGMPAGE pPageDst = &pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT]; … … 1173 1223 while (cPagesLeft-- > 0) 1174 1224 { 1175 rc = pgmPhysFreePage(pVM, pReq, &cPendingPages, pPageDst, GCPhys, enmType);1225 rc = pgmPhysFreePage(pVM, pReq, &cPendingPages, pPageDst, GCPhys, PGMPAGETYPE_MMIO); 1176 1226 AssertLogRelRCReturn(rc, rc); /* We're done for if this goes wrong. */ 1177 1227 1178 PGM_PAGE_SET_TYPE(pVM, pPageDst, enmType); 1228 PGM_PAGE_SET_TYPE(pVM, pPageDst, PGMPAGETYPE_MMIO); 1229 #ifdef VBOX_WITH_NATIVE_NEM 1230 if (u2State != UINT8_MAX) 1231 PGM_PAGE_SET_NEM_STATE(pPageDst, u2State); 1232 #endif 1179 1233 1180 1234 GCPhys += PAGE_SIZE; … … 1182 1236 } 1183 1237 1238 /* Finish pending and cleanup. */ 1184 1239 if (cPendingPages) 1185 1240 { … … 1634 1689 * PGMR3PhysRegisterRam worker that initializes and links a RAM range. 1635 1690 * 1691 * In NEM mode, this will allocate the pages backing the RAM range and this may 1692 * fail. NEM registration may also fail. (In regular HM mode it won't fail.) 1693 * 1694 * @returns VBox status code. 1636 1695 * @param pVM The cross context VM structure. 1637 1696 * @param pNew The new RAM range. … … 1644 1703 * @param pPrev The previous RAM range (for linking). 1645 1704 */ 1646 static voidpgmR3PhysInitAndLinkRamRange(PVM pVM, PPGMRAMRANGE pNew, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,1647 1705 static int pgmR3PhysInitAndLinkRamRange(PVM pVM, PPGMRAMRANGE pNew, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast, 1706 RTRCPTR RCPtrNew, RTR0PTR R0PtrNew, const char *pszDesc, PPGMRAMRANGE pPrev) 1648 1707 { 1649 1708 /* 1650 1709 * Initialize the range. 1651 1710 */ 1652 pNew->pSelfR0 = R0PtrNew != NIL_RTR0PTR ? R0PtrNew : MMHyperCCToR0(pVM, pNew);1711 pNew->pSelfR0 = R0PtrNew; 1653 1712 pNew->GCPhys = GCPhys; 1654 1713 pNew->GCPhysLast = GCPhysLast; 1655 1714 pNew->cb = GCPhysLast - GCPhys + 1; 1656 1715 pNew->pszDesc = pszDesc; 1657 pNew->fFlags = RCPtrNew != NIL_RTRCPTR ? PGM_RAM_RANGE_FLAGS_FLOATING : 0;1658 1716 pNew->pvR3 = NULL; 1659 1717 pNew->paLSPages = NULL; 1718 pNew->fFlags = 0; 1719 #ifndef PGM_WITHOUT_MAPPINGS 1720 if (RCPtrNew != NIL_RTRCPTR) 1721 pNew->fFlags |= PGM_RAM_RANGE_FLAGS_FLOATING; 1722 #else 1723 NOREF(RCPtrNew); 1724 #endif 1660 1725 1661 1726 uint32_t const cPages = pNew->cb >> PAGE_SHIFT; 1662 RTGCPHYS iPage = cPages; 1663 while (iPage-- > 0) 1664 PGM_PAGE_INIT_ZERO(&pNew->aPages[iPage], pVM, PGMPAGETYPE_RAM); 1665 1666 /* Update the page count stats. */ 1667 pVM->pgm.s.cZeroPages += cPages; 1668 pVM->pgm.s.cAllPages += cPages; 1727 #ifdef VBOX_WITH_PGM_NEM_MODE 1728 if (!pVM->pgm.s.fNemMode) 1729 #endif 1730 { 1731 RTGCPHYS iPage = cPages; 1732 while (iPage-- > 0) 1733 PGM_PAGE_INIT_ZERO(&pNew->aPages[iPage], pVM, PGMPAGETYPE_RAM); 1734 1735 /* Update the page count stats. */ 1736 pVM->pgm.s.cZeroPages += cPages; 1737 pVM->pgm.s.cAllPages += cPages; 1738 } 1739 #ifdef VBOX_WITH_PGM_NEM_MODE 1740 else 1741 { 1742 int rc = SUPR3PageAlloc(cPages, &pNew->pvR3); 1743 if (RT_FAILURE(rc)) 1744 return rc; 1745 1746 RTGCPHYS iPage = cPages; 1747 while (iPage-- > 0) 1748 PGM_PAGE_INIT(&pNew->aPages[iPage], UINT64_C(0x0000fffffffff000), NIL_GMM_PAGEID, 1749 PGMPAGETYPE_RAM, PGM_PAGE_STATE_ALLOCATED); 1750 1751 /* Update the page count stats. */ 1752 pVM->pgm.s.cPrivatePages += cPages; 1753 pVM->pgm.s.cAllPages += cPages; 1754 } 1755 #endif 1669 1756 1670 1757 /* … … 1672 1759 */ 1673 1760 pgmR3PhysLinkRamRange(pVM, pNew, pPrev); 1761 1762 /* 1763 * Notify NEM now that it has been linked. 1764 */ 1765 int rc = NEMR3NotifyPhysRamRegister(pVM, GCPhys, pNew->cb, pNew->pvR3); 1766 if (RT_FAILURE(rc)) 1767 pgmR3PhysUnlinkRamRange2(pVM, pNew, pPrev); 1768 return rc; 1674 1769 } 1675 1770 … … 1757 1852 * We push these in below the HMA. 1758 1853 */ 1759 RTGCPTR GCPtrChunkMap = pVM->pgm.s.GCPtrPrevRamRangeMapping - cbChunk; 1760 #ifndef PGM_WITHOUT_MAPPINGS 1854 #ifdef PGM_WITHOUT_MAPPINGS 1855 RTGCPTR const GCPtrChunk = NIL_RTGCPTR; 1856 RT_NOREF(cbChunk); 1857 #else 1858 RTGCPTR const GCPtrChunkMap = pVM->pgm.s.GCPtrPrevRamRangeMapping - cbChunk; 1761 1859 rc = PGMR3MapPT(pVM, GCPtrChunkMap, cbChunk, 0 /*fFlags*/, pgmR3PhysRamRangeRelocate, pNew, pszDescChunk); 1762 1860 if (RT_SUCCESS(rc)) 1763 #endif /* !PGM_WITHOUT_MAPPINGS */1764 1861 { 1765 1862 pVM->pgm.s.GCPtrPrevRamRangeMapping = GCPtrChunkMap; 1766 1863 1767 1864 RTGCPTR const GCPtrChunk = GCPtrChunkMap + PAGE_SIZE; 1768 #ifndef PGM_WITHOUT_MAPPINGS1769 1865 RTGCPTR GCPtrPage = GCPtrChunk; 1770 1866 for (uint32_t iPage = 0; iPage < cChunkPages && RT_SUCCESS(rc); iPage++, GCPtrPage += PAGE_SIZE) … … 1776 1872 * Ok, init and link the range. 1777 1873 */ 1778 pgmR3PhysInitAndLinkRamRange(pVM, pNew, GCPhys, GCPhys + ((RTGCPHYS)cRamPages << PAGE_SHIFT) - 1, 1779 (RTRCPTR)GCPtrChunk, R0PtrChunk, pszDescChunk, *ppPrev); 1780 *ppPrev = pNew; 1874 rc = pgmR3PhysInitAndLinkRamRange(pVM, pNew, GCPhys, GCPhys + ((RTGCPHYS)cRamPages << PAGE_SHIFT) - 1, 1875 (RTRCPTR)GCPtrChunk, R0PtrChunk, pszDescChunk, *ppPrev); 1876 if (RT_SUCCESS(rc)) 1877 *ppPrev = pNew; 1781 1878 } 1782 } 1879 #ifndef PGM_WITHOUT_MAPPINGS 1880 } 1881 #endif 1783 1882 1784 1883 if (RT_FAILURE(rc)) … … 1897 1996 PPGMRAMRANGE pNew; 1898 1997 rc = MMR3HyperAllocOnceNoRel(pVM, cbRamRange, 0, MM_TAG_PGM_PHYS, (void **)&pNew); 1899 AssertLogRelMsgRCReturn(rc, ("cbRamRange=%zu\n", cbRamRange), rc); 1900 1901 pgmR3PhysInitAndLinkRamRange(pVM, pNew, GCPhys, GCPhysLast, NIL_RTRCPTR, NIL_RTR0PTR, pszDesc, pPrev); 1998 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc cbRamRange=%zu\n", rc, cbRamRange), rc); 1999 2000 rc = pgmR3PhysInitAndLinkRamRange(pVM, pNew, GCPhys, GCPhysLast, NIL_RTRCPTR, MMHyperCCToR0(pVM, pNew), pszDesc, pPrev); 2001 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc cbRamRange=%zu\n", rc, cbRamRange), rc); 1902 2002 } 1903 2003 pgmPhysInvalidatePageMapTLB(pVM); 1904 2004 1905 /*1906 * Notify NEM while holding the lock (experimental) and REM without (like always).1907 */1908 rc = NEMR3NotifyPhysRamRegister(pVM, GCPhys, cb);1909 2005 PGM_UNLOCK(pVM); 1910 2006 return rc; … … 1926 2022 Assert(pVM->pgm.s.fRamPreAlloc); 1927 2023 Log(("pgmR3PhysRamPreAllocate: enter\n")); 2024 #ifdef VBOX_WITH_PGM_NEM_MODE 2025 AssertLogRelReturn(!pVM->pgm.s.fNemMode, VERR_PGM_NOT_SUPPORTED_FOR_NEM_MODE); 2026 #endif 1928 2027 1929 2028 /* … … 2100 2199 2101 2200 if ( !pVM->pgm.s.fRamPreAlloc 2201 #ifdef VBOX_WITH_PGM_NEM_MODE 2202 && !pVM->pgm.s.fNemMode 2203 #endif 2102 2204 && pVM->pgm.s.fZeroRamPagesOnReset) 2103 2205 { … … 2135 2237 case PGMPAGETYPE_SPECIAL_ALIAS_MMIO: /** @todo perhaps leave the special page alone? I don't think VT-x copes with this code. */ 2136 2238 pgmHandlerPhysicalResetAliasedPage(pVM, pPage, pRam->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT), 2137 true /*fDoAccounting*/);2239 pRam, true /*fDoAccounting*/); 2138 2240 break; 2139 2241 … … 2188 2290 case PGMPAGETYPE_SPECIAL_ALIAS_MMIO: /** @todo perhaps leave the special page alone? I don't think VT-x copes with this code. */ 2189 2291 pgmHandlerPhysicalResetAliasedPage(pVM, pPage, pRam->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT), 2190 true /*fDoAccounting*/);2292 pRam, true /*fDoAccounting*/); 2191 2293 break; 2192 2294 … … 2396 2498 * for PCI memory, but we're doing the same thing for MMIO2 pages. 2397 2499 */ 2398 rc = pgmR3PhysFreePageRange(pVM, pRam, GCPhys, GCPhysLast, PGMPAGETYPE_MMIO);2500 rc = pgmR3PhysFreePageRange(pVM, pRam, GCPhys, GCPhysLast, NULL); 2399 2501 AssertRCReturnStmt(rc, PGM_UNLOCK(pVM), rc); 2400 2502 … … 2409 2511 else 2410 2512 { 2411 2412 2513 /* 2413 2514 * No RAM range, insert an ad hoc one. … … 2418 2519 Log(("PGMR3PhysMMIORegister: Adding ad hoc MMIO range for %RGp-%RGp %s\n", GCPhys, GCPhysLast, pszDesc)); 2419 2520 2521 /* Alloc. */ 2420 2522 const uint32_t cPages = cb >> PAGE_SHIFT; 2421 2523 const size_t cbRamRange = RT_UOFFSETOF_DYN(PGMRAMRANGE, aPages[cPages]); 2422 2524 rc = MMHyperAlloc(pVM, RT_UOFFSETOF_DYN(PGMRAMRANGE, aPages[cPages]), 16, MM_TAG_PGM_PHYS, (void **)&pNew); 2423 2525 AssertLogRelMsgRCReturnStmt(rc, ("cbRamRange=%zu\n", cbRamRange), PGM_UNLOCK(pVM), rc); 2526 2527 #ifdef VBOX_WITH_NATIVE_NEM 2528 /* Notify NEM. */ 2529 uint8_t u2State = 0; /* (must have valid state as there can't be anything to preserve) */ 2530 if (VM_IS_NEM_ENABLED(pVM)) 2531 { 2532 rc = NEMR3NotifyPhysMmioExMapEarly(pVM, GCPhys, cPages << PAGE_SHIFT, 0 /*fFlags*/, NULL, NULL, &u2State); 2533 AssertLogRelRCReturnStmt(rc, MMHyperFree(pVM, pNew), rc); 2534 } 2535 #endif 2424 2536 2425 2537 /* Initialize the range. */ … … 2435 2547 uint32_t iPage = cPages; 2436 2548 while (iPage-- > 0) 2549 { 2437 2550 PGM_PAGE_INIT_ZERO(&pNew->aPages[iPage], pVM, PGMPAGETYPE_MMIO); 2551 #ifdef VBOX_WITH_NATIVE_NEM 2552 PGM_PAGE_SET_NEM_STATE(&pNew->aPages[iPage], u2State); 2553 #endif 2554 } 2438 2555 Assert(PGM_PAGE_GET_TYPE(&pNew->aPages[0]) == PGMPAGETYPE_MMIO); 2439 2556 … … 2450 2567 */ 2451 2568 rc = PGMHandlerPhysicalRegister(pVM, GCPhys, GCPhysLast, hType, pvUserR3, pvUserR0, pvUserRC, pszDesc); 2452 if ( RT_FAILURE(rc) 2453 && !fRamExists) 2569 if (RT_SUCCESS(rc)) 2570 { 2571 #ifdef VBOX_WITH_NATIVE_NEM 2572 /* Late NEM notification. */ 2573 if (VM_IS_NEM_ENABLED(pVM)) 2574 { 2575 uint32_t const fNemNotify = (fRamExists ? NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE : 0); 2576 rc = NEMR3NotifyPhysMmioExMapLate(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemNotify, 2577 fRamExists ? (uint8_t *)pRam->pvR3 + (uintptr_t)(GCPhys - pRam->GCPhys) : NULL, 2578 NULL); 2579 AssertLogRelRCReturn(rc, rc); 2580 } 2581 #endif 2582 } 2583 /** @todo the phys handler failure handling isn't complete, esp. wrt NEM. */ 2584 else if (!fRamExists) 2454 2585 { 2455 2586 pVM->pgm.s.cPureMmioPages -= cb >> PAGE_SHIFT; … … 2532 2663 Log(("PGMR3PhysMMIODeregister: Freeing ad hoc MMIO range for %RGp-%RGp %s\n", 2533 2664 GCPhys, GCPhysLast, pRam->pszDesc)); 2665 /** @todo check the ad-hoc flags? */ 2666 2667 #ifdef VBOX_WITH_NATIVE_NEM 2668 if (VM_IS_NEM_ENABLED(pVM)) /* Notify REM before we unlink the range. */ 2669 { 2670 rc = NEMR3NotifyPhysMmioExUnmap(pVM, GCPhys, GCPhysLast - GCPhys + 1, 0 /*fFlags*/, NULL, NULL, NULL); 2671 AssertLogRelRCReturn(rc, rc); 2672 } 2673 #endif 2534 2674 2535 2675 pVM->pgm.s.cAllPages -= cPages; … … 2568 2708 iPage++; 2569 2709 } 2710 2711 #ifdef VBOX_WITH_NATIVE_NEM 2712 /* Notify REM (failure will probably leave things in a non-working state). */ 2713 if (VM_IS_NEM_ENABLED(pVM)) 2714 { 2715 uint8_t u2State = UINT8_MAX; 2716 rc = NEMR3NotifyPhysMmioExUnmap(pVM, GCPhys, GCPhysLast - GCPhys + 1, NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE, 2717 pRam->pvR3 ? (uint8_t *)pRam->pvR3 + GCPhys - pRam->GCPhys : NULL, 2718 NULL, &u2State); 2719 AssertLogRelRCReturn(rc, rc); 2720 if (u2State != UINT8_MAX) 2721 pgmPhysSetNemStateForPages(&pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT], 2722 cb >> PAGE_SHIFT, u2State); 2723 } 2724 #endif 2570 2725 break; 2571 2726 } … … 3384 3539 * for PCI memory, but we're doing the same thing for MMIO2 pages. 3385 3540 * 3386 * We replace th isMMIO/ZERO pages with real pages in the MMIO2 case.3541 * We replace these MMIO/ZERO pages with real pages in the MMIO2 case. 3387 3542 */ 3388 3543 Assert(pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK); /* Only one chunk */ 3389 3390 int rc = pgmR3PhysFreePageRange(pVM, pRam, GCPhys, GCPhysLast, PGMPAGETYPE_MMIO); 3544 Assert(pFirstMmio->pvR3 == pFirstMmio->RamRange.pvR3); 3545 Assert(pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2 3546 ? pFirstMmio->RamRange.pvR3 != NULL : pFirstMmio->RamRange.pvR3 == NULL); 3547 3548 #ifdef VBOX_WITH_PGM_NEM_MODE 3549 /* We cannot mix MMIO2 into a RAM range in simplified memory mode because pRam->pvR3 can't point 3550 both at the RAM and MMIO2, so we won't ever write & read from the actual MMIO2 memory if we try. */ 3551 AssertLogRelMsgReturn(!pVM->pgm.s.fNemMode || !(pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2), 3552 ("%s at %RGp-%RGp\n", pFirstMmio->RamRange.pszDesc, GCPhys, GCPhysLast), 3553 VERR_PGM_NOT_SUPPORTED_FOR_NEM_MODE); 3554 #endif 3555 3556 int rc = pgmR3PhysFreePageRange(pVM, pRam, GCPhys, GCPhysLast, pFirstMmio->RamRange.pvR3); 3391 3557 AssertRCReturnStmt(rc, PGM_UNLOCK(pVM), rc); 3392 3558 … … 3410 3576 PGM_PAGE_SET_PTE_INDEX(pVM, pPageDst, 0); 3411 3577 PGM_PAGE_SET_TRACKING(pVM, pPageDst, 0); 3412 /* (We tell NEM at the end of the function.)*/3578 /* NEM state is set by pgmR3PhysFreePageRange. */ 3413 3579 3414 3580 pVM->pgm.s.cZeroPages--; … … 3436 3602 for (PPGMREGMMIO2RANGE pCurMmio = pFirstMmio; ; pCurMmio = pCurMmio->pNextR3) 3437 3603 { 3604 #ifdef VBOX_WITH_NATIVE_NEM 3605 /* Tell NEM and get the new NEM state for the pages. */ 3606 uint8_t u2NemState = 0; 3607 if (VM_IS_NEM_ENABLED(pVM)) 3608 { 3609 int rc = NEMR3NotifyPhysMmioExMapEarly(pVM, pCurMmio->RamRange.GCPhys, 3610 pCurMmio->RamRange.GCPhysLast - pCurMmio->RamRange.GCPhys + 1, 3611 pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2 3612 ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0, 3613 NULL, pCurMmio->RamRange.pvR3, &u2NemState); 3614 AssertLogRelRCReturnStmt(rc, PGM_UNLOCK(pVM), rc); 3615 } 3616 #endif 3617 3438 3618 /* Clear the tracking data of pages we're going to reactivate. */ 3439 3619 PPGMPAGE pPageSrc = &pCurMmio->RamRange.aPages[0]; … … 3443 3623 PGM_PAGE_SET_TRACKING(pVM, pPageSrc, 0); 3444 3624 PGM_PAGE_SET_PTE_INDEX(pVM, pPageSrc, 0); 3625 #ifdef VBOX_WITH_NATIVE_NEM 3626 PGM_PAGE_SET_NEM_STATE(pPageSrc, u2NemState); 3627 #endif 3445 3628 pPageSrc++; 3446 3629 } … … 3487 3670 { 3488 3671 pCurMmio->fFlags &= ~PGMREGMMIO2RANGE_F_MAPPED; 3489 pgmHandlerPhysicalExDeregister(pVM, pCurMmio->pPhysHandlerR3 , fRamExists);3672 pgmHandlerPhysicalExDeregister(pVM, pCurMmio->pPhysHandlerR3); 3490 3673 } 3491 3674 … … 3511 3694 } 3512 3695 3696 /** @todo NEM notification cleanup */ 3513 3697 PGM_UNLOCK(pVM); 3514 3698 return rc; … … 3531 3715 pgmPhysInvalidatePageMapTLB(pVM); 3532 3716 3533 /* 3534 * Notify NEM while holding the lock (experimental) and REM without (like always). 3535 */ 3536 uint32_t const fNemNotify = (pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2 ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0) 3537 | (pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_OVERLAPPING ? NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE : 0); 3538 int rc = NEMR3NotifyPhysMmioExMap(pVM, GCPhys, cbRange, fNemNotify, pFirstMmio->pvR3); 3717 #ifdef VBOX_WITH_NATIVE_NEM 3718 /* 3719 * Late NEM notification. 3720 */ 3721 if (VM_IS_NEM_ENABLED(pVM)) 3722 { 3723 int rc; 3724 uint32_t fNemFlags = pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2 ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0; 3725 if (fRamExists) 3726 rc = NEMR3NotifyPhysMmioExMapLate(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemFlags | NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE, 3727 pRam->pvR3 ? (uint8_t *)pRam->pvR3 + GCPhys - pRam->GCPhys : NULL, pFirstMmio->pvR3); 3728 else 3729 { 3730 rc = VINF_SUCCESS; 3731 for (PPGMREGMMIO2RANGE pCurMmio = pFirstMmio; ; pCurMmio = pCurMmio->pNextR3) 3732 { 3733 rc = NEMR3NotifyPhysMmioExMapLate(pVM, pCurMmio->RamRange.GCPhys, pCurMmio->RamRange.cb, fNemFlags, 3734 NULL, pCurMmio->RamRange.pvR3); 3735 if ((pCurMmio->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK) || RT_FAILURE(rc)) 3736 break; 3737 } 3738 } 3739 AssertLogRelRCReturnStmt(rc, PGMR3PhysMmio2Unmap(pVM, pDevIns, hMmio2, GCPhys); PGM_UNLOCK(pVM), rc); 3740 } 3741 #endif 3539 3742 3540 3743 PGM_UNLOCK(pVM); 3541 3744 3542 return rc;3745 return VINF_SUCCESS; 3543 3746 } 3544 3747 … … 3601 3804 3602 3805 PPGMREGMMIO2RANGE pCurMmio = pFirstMmio; 3603 rc = pgmHandlerPhysicalExDeregister(pVM, pFirstMmio->pPhysHandlerR3 , RT_BOOL(fOldFlags & PGMREGMMIO2RANGE_F_OVERLAPPING));3806 rc = pgmHandlerPhysicalExDeregister(pVM, pFirstMmio->pPhysHandlerR3); 3604 3807 AssertRCReturnStmt(rc, PGM_UNLOCK(pVM), rc); 3605 3808 while (!(pCurMmio->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK)) 3606 3809 { 3607 3810 pCurMmio = pCurMmio->pNextR3; 3608 rc = pgmHandlerPhysicalExDeregister(pVM, pCurMmio->pPhysHandlerR3 , RT_BOOL(fOldFlags & PGMREGMMIO2RANGE_F_OVERLAPPING));3811 rc = pgmHandlerPhysicalExDeregister(pVM, pCurMmio->pPhysHandlerR3); 3609 3812 AssertRCReturnStmt(rc, PGM_UNLOCK(pVM), VERR_PGM_PHYS_MMIO_EX_IPE); 3610 3813 } … … 3614 3817 * Unmap it. 3615 3818 */ 3616 RTGCPHYS const GCPhysRangeNotify = pFirstMmio->RamRange.GCPhys; 3819 int rcRet = VINF_SUCCESS; 3820 #ifdef VBOX_WITH_NATIVE_NEM 3821 uint32_t const fNemFlags = pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2 ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0; 3822 #endif 3617 3823 if (fOldFlags & PGMREGMMIO2RANGE_F_OVERLAPPING) 3618 3824 { … … 3632 3838 pRam = pRam->pNextR3; 3633 3839 3840 PPGMPAGE pPageDst = &pRam->aPages[(pFirstMmio->RamRange.GCPhys - pRam->GCPhys) >> PAGE_SHIFT]; 3634 3841 uint32_t cPagesLeft = pFirstMmio->RamRange.cb >> PAGE_SHIFT; 3635 3842 if (fOldFlags & PGMREGMMIO2RANGE_F_MMIO2) 3636 3843 pVM->pgm.s.cZeroPages += cPagesLeft; 3637 3844 3638 PPGMPAGE pPageDst = &pRam->aPages[(pFirstMmio->RamRange.GCPhys - pRam->GCPhys) >> PAGE_SHIFT]; 3845 #ifdef VBOX_WITH_NATIVE_NEM 3846 if (VM_IS_NEM_ENABLED(pVM)) /* Notify NEM. Note! we cannot be here in simple memory mode, see mapping function. */ 3847 { 3848 uint8_t u2State = UINT8_MAX; 3849 rc = NEMR3NotifyPhysMmioExUnmap(pVM, pFirstMmio->RamRange.GCPhys, pFirstMmio->RamRange.cb, 3850 fNemFlags | NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE, 3851 pRam->pvR3 3852 ? (uint8_t *)pRam->pvR3 + pFirstMmio->RamRange.GCPhys - pRam->GCPhys : NULL, 3853 pFirstMmio->pvR3, &u2State); 3854 AssertRCStmt(rc, rcRet = rc); 3855 if (u2State != UINT8_MAX) 3856 pgmPhysSetNemStateForPages(pPageDst, cPagesLeft, u2State); 3857 } 3858 #endif 3859 3639 3860 while (cPagesLeft-- > 0) 3640 3861 { … … 3658 3879 for (PPGMREGMMIO2RANGE pCurMmio = pFirstMmio; ; pCurMmio = pCurMmio->pNextR3) 3659 3880 { 3881 #ifdef VBOX_WITH_NATIVE_NEM 3882 if (VM_IS_NEM_ENABLED(pVM)) /* Notify NEM. */ 3883 { 3884 uint8_t u2State = UINT8_MAX; 3885 rc = NEMR3NotifyPhysMmioExUnmap(pVM, pCurMmio->RamRange.GCPhys, pCurMmio->RamRange.cb, fNemFlags, 3886 NULL, pCurMmio->pvR3, &u2State); 3887 AssertRCStmt(rc, rcRet = rc); 3888 if (u2State != UINT8_MAX) 3889 pgmPhysSetNemStateForPages(pCurMmio->RamRange.aPages, pCurMmio->RamRange.cb >> PAGE_SHIFT, u2State); 3890 } 3891 #endif 3660 3892 pgmR3PhysUnlinkRamRange(pVM, &pCurMmio->RamRange); 3661 3893 pCurMmio->RamRange.GCPhys = NIL_RTGCPHYS; … … 3677 3909 pgmPhysInvalidatePageMapTLB(pVM); 3678 3910 pgmPhysInvalidRamRangeTlbs(pVM); 3679 3680 /*3681 * Notify NEM while holding the lock (experimental) and REM without (like always).3682 */3683 uint32_t const fNemFlags = (fOldFlags & PGMREGMMIO2RANGE_F_MMIO2 ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0)3684 | (fOldFlags & PGMREGMMIO2RANGE_F_OVERLAPPING ? NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE : 0);3685 rc = NEMR3NotifyPhysMmioExUnmap(pVM, GCPhysRangeNotify, cbRange, fNemFlags);3686 3911 3687 3912 PGM_UNLOCK(pVM); … … 3931 4156 */ 3932 4157 static int pgmR3PhysRomRegisterLocked(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS cb, 3933 const void *pvBinary, uint32_t cbBinary, uint 32_t fFlags, const char *pszDesc)4158 const void *pvBinary, uint32_t cbBinary, uint8_t fFlags, const char *pszDesc) 3934 4159 { 3935 4160 /* … … 3969 4194 * Find the RAM location and check for conflicts. 3970 4195 * 3971 * Conflict detection is a bit different than for RAM 3972 * registration since a ROM can be located within a RAM 3973 * range. So, what we have to check for is other memory 3974 * types (other than RAM that is) and that we don't span 3975 * more than one RAM range (layz). 4196 * Conflict detection is a bit different than for RAM registration since a 4197 * ROM can be located within a RAM range. So, what we have to check for is 4198 * other memory types (other than RAM that is) and that we don't span more 4199 * than one RAM range (lazy). 3976 4200 */ 3977 4201 bool fRamExists = false; … … 4008 4232 pRam->GCPhys + ((RTGCPHYS)(uintptr_t)(pPage - &pRam->aPages[0]) << PAGE_SHIFT), 4009 4233 pPage, GCPhys, GCPhysLast, pszDesc), VERR_PGM_RAM_CONFLICT); 4010 Assert(PGM_PAGE_IS_ZERO(pPage) );4234 Assert(PGM_PAGE_IS_ZERO(pPage) || PGM_IS_IN_NEM_MODE(pVM)); 4011 4235 pPage++; 4012 4236 } … … 4026 4250 } 4027 4251 4028 /* 4029 * Allocate memory for the virgin copy of the RAM. 4030 */ 4031 PGMMALLOCATEPAGESREQ pReq; 4032 int rc = GMMR3AllocatePagesPrepare(pVM, &pReq, cPages, GMMACCOUNT_BASE); 4033 AssertRCReturn(rc, rc); 4034 4035 for (uint32_t iPage = 0; iPage < cPages; iPage++) 4036 { 4037 pReq->aPages[iPage].HCPhysGCPhys = GCPhys + (iPage << PAGE_SHIFT); 4038 pReq->aPages[iPage].idPage = NIL_GMM_PAGEID; 4039 pReq->aPages[iPage].idSharedPage = NIL_GMM_PAGEID; 4040 } 4041 4042 rc = GMMR3AllocatePagesPerform(pVM, pReq); 4043 if (RT_FAILURE(rc)) 4044 { 4045 GMMR3AllocatePagesCleanup(pReq); 4046 return rc; 4252 #ifdef VBOX_WITH_NATIVE_NEM 4253 /* 4254 * Early NEM notification before we've made any changes or anything. 4255 */ 4256 uint32_t const fNemNotify = (fRamExists ? NEM_NOTIFY_PHYS_ROM_F_REPLACE : 0) 4257 | (fFlags & PGMPHYS_ROM_FLAGS_SHADOWED ? NEM_NOTIFY_PHYS_ROM_F_SHADOW : 0); 4258 uint8_t u2NemState = UINT8_MAX; 4259 if (VM_IS_NEM_ENABLED(pVM)) 4260 { 4261 int rc = NEMR3NotifyPhysRomRegisterEarly(pVM, GCPhys, cPages << PAGE_SHIFT, 4262 fRamExists ? PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhys) : NULL, 4263 fNemNotify, &u2NemState); 4264 AssertLogRelRCReturn(rc, rc); 4265 } 4266 #endif 4267 4268 /* 4269 * Allocate memory for the virgin copy of the RAM. In simplified memory mode, 4270 * we allocate memory for any ad-hoc RAM range and for shadow pages. 4271 */ 4272 PGMMALLOCATEPAGESREQ pReq = NULL; 4273 #ifdef VBOX_WITH_PGM_NEM_MODE 4274 void *pvRam = NULL; 4275 void *pvAlt = NULL; 4276 if (pVM->pgm.s.fNemMode) 4277 { 4278 if (!fRamExists) 4279 { 4280 int rc = SUPR3PageAlloc(cPages, &pvRam); 4281 if (RT_FAILURE(rc)) 4282 return rc; 4283 } 4284 if (fFlags & PGMPHYS_ROM_FLAGS_SHADOWED) 4285 { 4286 int rc = SUPR3PageAlloc(cPages, &pvAlt); 4287 if (RT_FAILURE(rc)) 4288 { 4289 if (pvRam) 4290 SUPR3PageFree(pvRam, cPages); 4291 return rc; 4292 } 4293 } 4294 } 4295 else 4296 #endif 4297 { 4298 int rc = GMMR3AllocatePagesPrepare(pVM, &pReq, cPages, GMMACCOUNT_BASE); 4299 AssertRCReturn(rc, rc); 4300 4301 for (uint32_t iPage = 0; iPage < cPages; iPage++) 4302 { 4303 pReq->aPages[iPage].HCPhysGCPhys = GCPhys + (iPage << PAGE_SHIFT); 4304 pReq->aPages[iPage].idPage = NIL_GMM_PAGEID; 4305 pReq->aPages[iPage].idSharedPage = NIL_GMM_PAGEID; 4306 } 4307 4308 rc = GMMR3AllocatePagesPerform(pVM, pReq); 4309 if (RT_FAILURE(rc)) 4310 { 4311 GMMR3AllocatePagesCleanup(pReq); 4312 return rc; 4313 } 4047 4314 } 4048 4315 … … 4051 4318 */ 4052 4319 PPGMROMRANGE pRomNew; 4053 rc = MMHyperAlloc(pVM, RT_UOFFSETOF_DYN(PGMROMRANGE, aPages[cPages]), 0, MM_TAG_PGM_PHYS, (void **)&pRomNew);4320 int rc = MMHyperAlloc(pVM, RT_UOFFSETOF_DYN(PGMROMRANGE, aPages[cPages]), 0, MM_TAG_PGM_PHYS, (void **)&pRomNew); 4054 4321 if (RT_SUCCESS(rc)) 4055 4322 { … … 4062 4329 * Initialize and insert the RAM range (if required). 4063 4330 */ 4331 uint32_t const idxFirstRamPage = fRamExists ? (GCPhys - pRam->GCPhys) >> PAGE_SHIFT : 0; 4064 4332 PPGMROMPAGE pRomPage = &pRomNew->aPages[0]; 4065 4333 if (!fRamExists) 4066 4334 { 4335 /* New RAM range. */ 4067 4336 pRamNew->pSelfR0 = MMHyperCCToR0(pVM, pRamNew); 4068 4337 pRamNew->GCPhys = GCPhys; … … 4074 4343 pRamNew->paLSPages = NULL; 4075 4344 4076 PPGMPAGE pPage = &pRamNew->aPages[0]; 4077 for (uint32_t iPage = 0; iPage < cPages; iPage++, pPage++, pRomPage++) 4345 PPGMPAGE pRamPage = &pRamNew->aPages[idxFirstRamPage]; 4346 #ifdef VBOX_WITH_PGM_NEM_MODE 4347 if (pVM->pgm.s.fNemMode) 4078 4348 { 4079 PGM_PAGE_INIT(pPage, 4080 pReq->aPages[iPage].HCPhysGCPhys, 4081 pReq->aPages[iPage].idPage, 4082 PGMPAGETYPE_ROM, 4083 PGM_PAGE_STATE_ALLOCATED); 4084 4085 pRomPage->Virgin = *pPage; 4349 AssertPtr(pvRam); Assert(pReq == NULL); 4350 pRamNew->pvR3 = pvRam; 4351 for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++, pRomPage++) 4352 { 4353 PGM_PAGE_INIT(pRamPage, UINT64_C(0x0000fffffffff000), NIL_GMM_PAGEID, 4354 PGMPAGETYPE_ROM, PGM_PAGE_STATE_ALLOCATED); 4355 pRomPage->Virgin = *pRamPage; 4356 } 4086 4357 } 4087 4088 pVM->pgm.s.cAllPages += cPages; 4358 else 4359 #endif 4360 for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++, pRomPage++) 4361 { 4362 PGM_PAGE_INIT(pRamPage, 4363 pReq->aPages[iPage].HCPhysGCPhys, 4364 pReq->aPages[iPage].idPage, 4365 PGMPAGETYPE_ROM, 4366 PGM_PAGE_STATE_ALLOCATED); 4367 4368 pRomPage->Virgin = *pRamPage; 4369 } 4370 4371 pVM->pgm.s.cAllPages += cPages; 4372 pVM->pgm.s.cPrivatePages += cPages; 4089 4373 pgmR3PhysLinkRamRange(pVM, pRamNew, pRamPrev); 4090 4374 } 4091 4375 else 4092 4376 { 4093 PPGMPAGE pPage = &pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT]; 4094 for (uint32_t iPage = 0; iPage < cPages; iPage++, pPage++, pRomPage++) 4377 /* Existing RAM range. */ 4378 PPGMPAGE pRamPage = &pRam->aPages[idxFirstRamPage]; 4379 #ifdef VBOX_WITH_PGM_NEM_MODE 4380 if (pVM->pgm.s.fNemMode) 4095 4381 { 4096 PGM_PAGE_SET_TYPE(pVM, pPage, PGMPAGETYPE_ROM); 4097 PGM_PAGE_SET_HCPHYS(pVM, pPage, pReq->aPages[iPage].HCPhysGCPhys); 4098 PGM_PAGE_SET_STATE(pVM, pPage, PGM_PAGE_STATE_ALLOCATED); 4099 PGM_PAGE_SET_PAGEID(pVM, pPage, pReq->aPages[iPage].idPage); 4100 PGM_PAGE_SET_PDE_TYPE(pVM, pPage, PGM_PAGE_PDE_TYPE_DONTCARE); 4101 PGM_PAGE_SET_PTE_INDEX(pVM, pPage, 0); 4102 PGM_PAGE_SET_TRACKING(pVM, pPage, 0); 4103 4104 pRomPage->Virgin = *pPage; 4382 Assert(pvRam == NULL); Assert(pReq == NULL); 4383 for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++, pRomPage++) 4384 { 4385 Assert(PGM_PAGE_GET_HCPHYS(pRamPage) == UINT64_C(0x0000fffffffff000)); 4386 Assert(PGM_PAGE_GET_PAGEID(pRamPage) == NIL_GMM_PAGEID); 4387 Assert(PGM_PAGE_GET_STATE(pRamPage) == PGM_PAGE_STATE_ALLOCATED); 4388 PGM_PAGE_SET_TYPE(pVM, pRamPage, PGMPAGETYPE_ROM); 4389 PGM_PAGE_SET_STATE(pVM, pRamPage, PGM_PAGE_STATE_ALLOCATED); 4390 PGM_PAGE_SET_PDE_TYPE(pVM, pRamPage, PGM_PAGE_PDE_TYPE_DONTCARE); 4391 PGM_PAGE_SET_PTE_INDEX(pVM, pRamPage, 0); 4392 PGM_PAGE_SET_TRACKING(pVM, pRamPage, 0); 4393 4394 pRomPage->Virgin = *pRamPage; 4395 } 4105 4396 } 4106 4397 else 4398 #endif 4399 { 4400 for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++, pRomPage++) 4401 { 4402 PGM_PAGE_SET_TYPE(pVM, pRamPage, PGMPAGETYPE_ROM); 4403 PGM_PAGE_SET_HCPHYS(pVM, pRamPage, pReq->aPages[iPage].HCPhysGCPhys); 4404 PGM_PAGE_SET_STATE(pVM, pRamPage, PGM_PAGE_STATE_ALLOCATED); 4405 PGM_PAGE_SET_PAGEID(pVM, pRamPage, pReq->aPages[iPage].idPage); 4406 PGM_PAGE_SET_PDE_TYPE(pVM, pRamPage, PGM_PAGE_PDE_TYPE_DONTCARE); 4407 PGM_PAGE_SET_PTE_INDEX(pVM, pRamPage, 0); 4408 PGM_PAGE_SET_TRACKING(pVM, pRamPage, 0); 4409 4410 pRomPage->Virgin = *pRamPage; 4411 } 4412 pVM->pgm.s.cZeroPages -= cPages; 4413 pVM->pgm.s.cPrivatePages += cPages; 4414 } 4107 4415 pRamNew = pRam; 4108 4109 pVM->pgm.s.cZeroPages -= cPages;4110 4416 } 4111 pVM->pgm.s.cPrivatePages += cPages; 4417 4418 /* Set the NEM state of the pages if needed. */ 4419 if (u2NemState != UINT8_MAX) 4420 pgmPhysSetNemStateForPages(&pRamNew->aPages[idxFirstRamPage], cPages, u2NemState); 4112 4421 4113 4422 /* Flush physical page map TLB. */ 4114 4423 pgmPhysInvalidatePageMapTLB(pVM); 4115 4424 4116 4117 /* Notify NEM before we register handlers. */ 4118 uint32_t const fNemNotify = (fRamExists ? NEM_NOTIFY_PHYS_ROM_F_REPLACE : 0) 4119 | (fFlags & PGMPHYS_ROM_FLAGS_SHADOWED ? NEM_NOTIFY_PHYS_ROM_F_SHADOW : 0); 4120 rc = NEMR3NotifyPhysRomRegisterEarly(pVM, GCPhys, cb, fNemNotify); 4121 4122 /* Register the ROM access handler. */ 4123 if (RT_SUCCESS(rc)) 4124 rc = PGMHandlerPhysicalRegister(pVM, GCPhys, GCPhysLast, pVM->pgm.s.hRomPhysHandlerType, 4125 pRomNew, MMHyperCCToR0(pVM, pRomNew), MMHyperCCToRC(pVM, pRomNew), 4126 pszDesc); 4425 /* 4426 * Register the ROM access handler. 4427 */ 4428 rc = PGMHandlerPhysicalRegister(pVM, GCPhys, GCPhysLast, pVM->pgm.s.hRomPhysHandlerType, 4429 pRomNew, MMHyperCCToR0(pVM, pRomNew), MMHyperCCToRC(pVM, pRomNew), pszDesc); 4127 4430 if (RT_SUCCESS(rc)) 4128 4431 { … … 4132 4435 */ 4133 4436 size_t cbBinaryLeft = cbBinary; 4134 PPGMPAGE pRamPage = &pRamNew->aPages[ (GCPhys - pRamNew->GCPhys) >> PAGE_SHIFT];4437 PPGMPAGE pRamPage = &pRamNew->aPages[idxFirstRamPage]; 4135 4438 for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++) 4136 4439 { … … 4170 4473 pRomNew->cbOriginal = cbBinary; 4171 4474 pRomNew->pszDesc = pszDesc; 4475 #ifdef VBOX_WITH_PGM_NEM_MODE 4476 pRomNew->pbR3Alternate = (uint8_t *)pvAlt; 4477 #endif 4172 4478 pRomNew->pvOriginal = fFlags & PGMPHYS_ROM_FLAGS_PERMANENT_BINARY 4173 4479 ? pvBinary : RTMemDup(pvBinary, cbBinary); … … 4178 4484 PPGMROMPAGE pPage = &pRomNew->aPages[iPage]; 4179 4485 pPage->enmProt = PGMROMPROT_READ_ROM_WRITE_IGNORE; 4180 PGM_PAGE_INIT_ZERO(&pPage->Shadow, pVM, PGMPAGETYPE_ROM_SHADOW); 4486 #ifdef VBOX_WITH_PGM_NEM_MODE 4487 if (pVM->pgm.s.fNemMode) 4488 PGM_PAGE_INIT(&pPage->Shadow, UINT64_C(0x0000fffffffff000), NIL_GMM_PAGEID, 4489 PGMPAGETYPE_ROM_SHADOW, PGM_PAGE_STATE_ALLOCATED); 4490 else 4491 #endif 4492 PGM_PAGE_INIT_ZERO(&pPage->Shadow, pVM, PGMPAGETYPE_ROM_SHADOW); 4181 4493 } 4182 4494 … … 4184 4496 if (fFlags & PGMPHYS_ROM_FLAGS_SHADOWED) 4185 4497 { 4186 pVM->pgm.s.cZeroPages += cPages; 4187 pVM->pgm.s.cAllPages += cPages; 4498 #ifdef VBOX_WITH_PGM_NEM_MODE 4499 if (pVM->pgm.s.fNemMode) 4500 pVM->pgm.s.cPrivatePages += cPages; 4501 else 4502 #endif 4503 pVM->pgm.s.cZeroPages += cPages; 4504 pVM->pgm.s.cAllPages += cPages; 4188 4505 } 4189 4506 … … 4206 4523 4207 4524 pgmPhysInvalidatePageMapTLB(pVM); 4208 GMMR3AllocatePagesCleanup(pReq); 4209 4210 /* Notify NEM again. */ 4211 return NEMR3NotifyPhysRomRegisterLate(pVM, GCPhys, cb, fNemNotify); 4525 #ifdef VBOX_WITH_PGM_NEM_MODE 4526 if (!pVM->pgm.s.fNemMode) 4527 #endif 4528 GMMR3AllocatePagesCleanup(pReq); 4529 4530 /* 4531 * Notify NEM again. 4532 */ 4533 u2NemState = UINT8_MAX; 4534 rc = NEMR3NotifyPhysRomRegisterLate(pVM, GCPhys, cb, PGM_RAMRANGE_CALC_PAGE_R3PTR(pRamNew, GCPhys), 4535 fNemNotify, &u2NemState); 4536 if (u2NemState != UINT8_MAX) 4537 pgmPhysSetNemStateForPages(&pRamNew->aPages[idxFirstRamPage], cPages, u2NemState); 4538 if (RT_SUCCESS(rc)) 4539 return rc; 4540 4541 /* 4542 * bail out 4543 */ 4544 /* unlink */ 4545 if (pRomPrev) 4546 { 4547 pRomPrev->pNextR3 = pRom; 4548 pRomPrev->pNextR0 = pRom ? MMHyperCCToR0(pVM, pRom) : NIL_RTR0PTR; 4549 } 4550 else 4551 { 4552 pVM->pgm.s.pRomRangesR3 = pRom; 4553 pVM->pgm.s.pRomRangesR0 = pRom ? MMHyperCCToR0(pVM, pRom) : NIL_RTR0PTR; 4554 } 4555 4556 if (fFlags & PGMPHYS_ROM_FLAGS_SHADOWED) 4557 { 4558 #ifdef VBOX_WITH_PGM_NEM_MODE 4559 if (pVM->pgm.s.fNemMode) 4560 pVM->pgm.s.cPrivatePages -= cPages; 4561 else 4562 #endif 4563 pVM->pgm.s.cZeroPages -= cPages; 4564 pVM->pgm.s.cAllPages -= cPages; 4565 } 4566 4212 4567 } 4213 4214 /* bail out */ 4215 rc = VERR_NO_MEMORY; 4568 else 4569 rc = VERR_NO_MEMORY; 4216 4570 } 4217 4571 … … 4225 4579 MMHyperFree(pVM, pRamNew); 4226 4580 } 4581 else 4582 { 4583 PPGMPAGE pRamPage = &pRam->aPages[idxFirstRamPage]; 4584 #ifdef VBOX_WITH_PGM_NEM_MODE 4585 if (pVM->pgm.s.fNemMode) 4586 { 4587 Assert(pvRam == NULL); Assert(pReq == NULL); 4588 for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++, pRomPage++) 4589 { 4590 Assert(PGM_PAGE_GET_HCPHYS(pRamPage) == UINT64_C(0x0000fffffffff000)); 4591 Assert(PGM_PAGE_GET_PAGEID(pRamPage) == NIL_GMM_PAGEID); 4592 Assert(PGM_PAGE_GET_STATE(pRamPage) == PGM_PAGE_STATE_ALLOCATED); 4593 PGM_PAGE_SET_TYPE(pVM, pRamPage, PGMPAGETYPE_RAM); 4594 PGM_PAGE_SET_STATE(pVM, pRamPage, PGM_PAGE_STATE_ALLOCATED); 4595 } 4596 } 4597 else 4598 #endif 4599 { 4600 for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++) 4601 PGM_PAGE_INIT_ZERO(pRamPage, pVM, PGMPAGETYPE_RAM); 4602 pVM->pgm.s.cZeroPages += cPages; 4603 pVM->pgm.s.cPrivatePages -= cPages; 4604 } 4605 } 4227 4606 } 4228 4607 MMHyperFree(pVM, pRomNew); … … 4230 4609 4231 4610 /** @todo Purge the mapping cache or something... */ 4232 GMMR3FreeAllocatedPages(pVM, pReq); 4233 GMMR3AllocatePagesCleanup(pReq); 4611 #ifdef VBOX_WITH_PGM_NEM_MODE 4612 if (pVM->pgm.s.fNemMode) 4613 { 4614 Assert(!pReq); 4615 if (pvRam) 4616 SUPR3PageFree(pvRam, cPages); 4617 if (pvAlt) 4618 SUPR3PageFree(pvAlt, cPages); 4619 } 4620 else 4621 #endif 4622 { 4623 GMMR3FreeAllocatedPages(pVM, pReq); 4624 GMMR3AllocatePagesCleanup(pReq); 4625 } 4234 4626 return rc; 4235 4627 } … … 4267 4659 */ 4268 4660 VMMR3DECL(int) PGMR3PhysRomRegister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS cb, 4269 const void *pvBinary, uint32_t cbBinary, uint 32_t fFlags, const char *pszDesc)4661 const void *pvBinary, uint32_t cbBinary, uint8_t fFlags, const char *pszDesc) 4270 4662 { 4271 4663 Log(("PGMR3PhysRomRegister: pDevIns=%p GCPhys=%RGp(-%RGp) cb=%RGp pvBinary=%p cbBinary=%#x fFlags=%#x pszDesc=%s\n", … … 4308 4700 * out all the dirty pages and replace them by the zero page. 4309 4701 */ 4702 #ifdef VBOX_WITH_PGM_NEM_MODE 4703 if (pVM->pgm.s.fNemMode) 4704 { 4705 /* Clear all the shadow pages (currently using alternate backing). */ 4706 RT_BZERO(pRom->pbR3Alternate, pRom->cb); 4707 } 4708 else 4709 #endif 4310 4710 if (!pVM->pgm.s.fRamPreAlloc) 4311 4711 { … … 4467 4867 * Iterate the relevant pages and make necessary the changes. 4468 4868 */ 4869 #ifdef VBOX_WITH_NATIVE_NEM 4870 PPGMRAMRANGE const pRam = pgmPhysGetRange(pVM, GCPhys); 4871 AssertPtrReturn(pRam, VERR_INTERNAL_ERROR_3); 4872 #endif 4469 4873 bool fChanges = false; 4470 4874 uint32_t const cPages = pRom->GCPhysLast <= GCPhysLast … … 4481 4885 4482 4886 /* flush references to the page. */ 4483 PPGMPAGE pRamPage = pgmPhysGetPage(pVM, pRom->GCPhys + (iPage << PAGE_SHIFT));4484 int rc2 = pgmPoolTrackUpdateGCPhys(pVM, pRom->GCPhys + (iPage << PAGE_SHIFT), pRamPage,4485 4887 RTGCPHYS const GCPhysPage = pRom->GCPhys + (iPage << PAGE_SHIFT); 4888 PPGMPAGE pRamPage = pgmPhysGetPage(pVM, GCPhysPage); 4889 int rc2 = pgmPoolTrackUpdateGCPhys(pVM, GCPhysPage, pRamPage, true /*fFlushPTEs*/, &fFlushTLB); 4486 4890 if (rc2 != VINF_SUCCESS && (rc == VINF_SUCCESS || RT_FAILURE(rc2))) 4487 4891 rc = rc2; … … 4495 4899 /** @todo preserve the volatile flags (handlers) when these have been moved out of HCPhys! */ 4496 4900 4901 #ifdef VBOX_WITH_NATIVE_NEM 4902 # ifdef VBOX_WITH_PGM_NEM_MODE 4903 /* In simplified mode we have to switch the page data around too. */ 4904 if (pVM->pgm.s.fNemMode) 4905 { 4906 uint8_t abPage[PAGE_SIZE]; 4907 uint8_t * const pbRamPage = PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhysPage); 4908 memcpy(abPage, &pRom->pbR3Alternate[(size_t)iPage << PAGE_SHIFT], sizeof(abPage)); 4909 memcpy(&pRom->pbR3Alternate[(size_t)iPage << PAGE_SHIFT], pbRamPage, sizeof(abPage)); 4910 memcpy(pbRamPage, abPage, sizeof(abPage)); 4911 } 4912 # endif 4497 4913 /* Tell NEM about the backing and protection change. */ 4498 4914 if (VM_IS_NEM_ENABLED(pVM)) … … 4500 4916 PGMPAGETYPE enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pNew); 4501 4917 NEMHCNotifyPhysPageChanged(pVM, GCPhys, PGM_PAGE_GET_HCPHYS(pOld), PGM_PAGE_GET_HCPHYS(pNew), 4918 PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhysPage), 4502 4919 pgmPhysPageCalcNemProtection(pRamPage, enmType), enmType, &u2State); 4503 4920 PGM_PAGE_SET_NEM_STATE(pRamPage, u2State); 4504 4921 } 4922 #endif 4505 4923 } 4506 4924 pRomPage->enmProt = enmProt; … … 5216 5634 * 5217 5635 * @param pVM The cross context VM structure. 5218 * @param pReq Pointer to the request. 5636 * @param pReq Pointer to the request. This is NULL when doing a 5637 * bulk free in NEM memory mode. 5219 5638 * @param pcPendingPages Where the number of pages waiting to be freed are 5220 * kept. This will normally be incremented. 5639 * kept. This will normally be incremented. This is 5640 * NULL when doing a bulk free in NEM memory mode. 5221 5641 * @param pPage Pointer to the page structure. 5222 5642 * @param GCPhys The guest physical address of the page, if applicable. … … 5250 5670 const uint32_t idPage = PGM_PAGE_GET_PAGEID(pPage); 5251 5671 Log3(("pgmPhysFreePage: idPage=%#x GCPhys=%RGp pPage=%R[pgmpage]\n", idPage, GCPhys, pPage)); 5252 if (RT_UNLIKELY( idPage == NIL_GMM_PAGEID 5253 || idPage > GMM_PAGEID_LAST 5254 || PGM_PAGE_GET_CHUNKID(pPage) == NIL_GMM_CHUNKID)) 5672 if (RT_UNLIKELY(!PGM_IS_IN_NEM_MODE(pVM) 5673 ? idPage == NIL_GMM_PAGEID 5674 || idPage > GMM_PAGEID_LAST 5675 || PGM_PAGE_GET_CHUNKID(pPage) == NIL_GMM_CHUNKID 5676 : idPage != NIL_GMM_PAGEID)) 5255 5677 { 5256 5678 AssertMsgFailed(("GCPhys=%RGp pPage=%R[pgmpage]\n", GCPhys, pPage)); … … 5286 5708 pgmPhysInvalidatePageMapTLBEntry(pVM, GCPhys); 5287 5709 5710 #ifdef VBOX_WITH_PGM_NEM_MODE 5711 /* 5712 * Skip the rest if we're doing a bulk free in NEM memory mode. 5713 */ 5714 if (!pReq) 5715 return VINF_SUCCESS; 5716 AssertLogRelReturn(!pVM->pgm.s.fNemMode, VERR_PGM_NOT_SUPPORTED_FOR_NEM_MODE); 5717 #endif 5718 5719 #ifdef VBOX_WITH_NATIVE_NEM 5288 5720 /* Notify NEM. */ 5289 /** @todo consider doing batch NEM notifications.*/5721 /** @todo Remove this one? */ 5290 5722 if (VM_IS_NEM_ENABLED(pVM)) 5291 5723 { 5292 5724 uint8_t u2State = PGM_PAGE_GET_NEM_STATE(pPage); 5293 NEMHCNotifyPhysPageChanged(pVM, GCPhys, HCPhysPrev, pVM->pgm.s.HCPhysZeroPg, 5725 NEMHCNotifyPhysPageChanged(pVM, GCPhys, HCPhysPrev, pVM->pgm.s.HCPhysZeroPg, pVM->pgm.s.pvZeroPgR3, 5294 5726 pgmPhysPageCalcNemProtection(pPage, enmNewType), enmNewType, &u2State); 5295 5727 PGM_PAGE_SET_NEM_STATE(pPage, u2State); 5296 5728 } 5729 #endif 5297 5730 5298 5731 /*
Note:
See TracChangeset
for help on using the changeset viewer.