Index: trunk/src/VBox/VMM/PGMInternal.h
===================================================================
--- trunk/src/VBox/VMM/PGMInternal.h	(revision 27005)
+++ trunk/src/VBox/VMM/PGMInternal.h	(revision 27026)
@@ -83,4 +83,11 @@
 #endif
 //#endif
+
+/**
+ * Large page support enabled only on 64 bits hosts; applies to nested paging only.
+ */
+#if (HC_ARCH_BITS == 64) && !defined(IN_RC)
+# define PGM_WITH_LARGE_PAGES
+#endif
 
 /**
@@ -3369,9 +3376,9 @@
 int             pgmPoolSyncCR3(PVMCPU pVCpu);
 bool            pgmPoolIsDirtyPage(PVM pVM, RTGCPHYS GCPhys);
-int             pgmPoolTrackUpdateGCPhys(PVM pVM, PPGMPAGE pPhysPage, bool fFlushPTEs, bool *pfFlushTLBs);
+int             pgmPoolTrackUpdateGCPhys(PVM pVM, RTGCPHYS GCPhysPage, PPGMPAGE pPhysPage, bool fFlushPTEs, bool *pfFlushTLBs);
 void            pgmPoolInvalidateDirtyPage(PVM pVM, RTGCPHYS GCPhysPT);
-DECLINLINE(int) pgmPoolTrackFlushGCPhys(PVM pVM, PPGMPAGE pPhysPage, bool *pfFlushTLBs)
+DECLINLINE(int) pgmPoolTrackFlushGCPhys(PVM pVM, RTGCPHYS GCPhysPage, PPGMPAGE pPhysPage, bool *pfFlushTLBs)
 {
-    return pgmPoolTrackUpdateGCPhys(pVM, pPhysPage, true /* flush PTEs */, pfFlushTLBs);
+    return pgmPoolTrackUpdateGCPhys(pVM, GCPhysPage, pPhysPage, true /* flush PTEs */, pfFlushTLBs);
 }
 
Index: trunk/src/VBox/VMM/PGMPhys.cpp
===================================================================
--- trunk/src/VBox/VMM/PGMPhys.cpp	(revision 27005)
+++ trunk/src/VBox/VMM/PGMPhys.cpp	(revision 27026)
@@ -2862,5 +2862,5 @@
                     /* flush references to the page. */
                     PPGMPAGE pRamPage = pgmPhysGetPage(&pVM->pgm.s, pRom->GCPhys + (iPage << PAGE_SHIFT));
-                    int rc2 = pgmPoolTrackFlushGCPhys(pVM, pRamPage, &fFlushTLB);
+                    int rc2 = pgmPoolTrackFlushGCPhys(pVM, pRom->GCPhys + (iPage << PAGE_SHIFT), pRamPage, &fFlushTLB);
                     if (rc2 != VINF_SUCCESS && (rc == VINF_SUCCESS || RT_FAILURE(rc2)))
                         rc = rc2;
Index: trunk/src/VBox/VMM/VMMAll/PGMAllBth.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 27005)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 27026)
@@ -2955,5 +2955,5 @@
     Assert(!PdeDst.n.u1Present); /* We're only supposed to call SyncPT on PDE!P and conflicts.*/
 
-# if (HC_ARCH_BITS == 64) && (PGM_SHW_TYPE != PGM_TYPE_32BIT && PGM_SHW_TYPE != PGM_TYPE_PAE)
+# if defined(PGM_WITH_LARGE_PAGES) && (PGM_SHW_TYPE != PGM_TYPE_32BIT && PGM_SHW_TYPE != PGM_TYPE_PAE)
 #  if  (PGM_SHW_TYPE != PGM_TYPE_EPT)   /* PGM_TYPE_EPT implies nested paging */
     if (HWACCMIsNestedPagingActive(pVM))
@@ -3001,4 +3001,7 @@
 #  endif
                 ASMAtomicWriteSize(pPdeDst, PdeDst.u);
+
+                /* Add a reference to the first page only. */
+                PGM_BTH_NAME(SyncPageWorkerTrackAddref)(pVCpu, pShwPde, PGM_PAGE_GET_TRACKING(pPage), pPage, iPDDst);
 
                 STAM_PROFILE_STOP(&pVCpu->pgm.s.CTX_MID_Z(Stat,SyncPT), a);
Index: trunk/src/VBox/VMM/VMMAll/PGMAllHandler.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllHandler.cpp	(revision 27005)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllHandler.cpp	(revision 27026)
@@ -223,5 +223,5 @@
             PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, uState);
 
-            int rc2 = pgmPoolTrackUpdateGCPhys(pVM, pPage, false /* allow updates of PTEs (instead of flushing) */, &fFlushTLBs);
+            int rc2 = pgmPoolTrackUpdateGCPhys(pVM, pRam->GCPhys + (i << PAGE_SHIFT), pPage, false /* allow updates of PTEs (instead of flushing) */, &fFlushTLBs);
             if (rc2 != VINF_SUCCESS && rc == VINF_SUCCESS)
                 rc = rc2;
@@ -411,5 +411,5 @@
      */
     bool fFlushTLBs = false;
-    int rc = pgmPoolTrackFlushGCPhys(pVM, pPage, &fFlushTLBs);
+    int rc = pgmPoolTrackFlushGCPhys(pVM, GCPhysPage, pPage, &fFlushTLBs);
     AssertLogRelRCReturnVoid(rc);
 # ifdef IN_RC
Index: trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp	(revision 27005)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp	(revision 27026)
@@ -368,5 +368,5 @@
     Assert(!PGM_PAGE_IS_MMIO(pPage));
 
-# if HC_ARCH_BITS == 64
+# ifdef PGM_WITH_LARGE_PAGES
     if (    PGMIsUsingLargePages(pVM)
         &&  PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_RAM)
@@ -385,5 +385,5 @@
      */
     bool fFlushTLBs = false;
-    int rc = pgmPoolTrackFlushGCPhys(pVM, pPage, &fFlushTLBs);
+    int rc = pgmPoolTrackFlushGCPhys(pVM, GCPhys, pPage, &fFlushTLBs);
     AssertMsgReturn(rc == VINF_SUCCESS || rc == VINF_PGM_SYNC_CR3, ("%Rrc\n", rc), RT_FAILURE(rc) ? rc : VERR_IPE_UNEXPECTED_STATUS);
 
@@ -456,4 +456,5 @@
 }
 
+#ifdef PGM_WITH_LARGE_PAGES
 /**
  * Replace a 2 MB range of zero pages with new pages that we can write to.
@@ -529,9 +530,9 @@
             else
             {
-#ifdef IN_RING3
+# ifdef IN_RING3
                 rc = PGMR3PhysAllocateLargeHandyPage(pVM, GCPhysBase);
-#else
+# else
                 rc = VMMRZCallRing3NoCpu(pVM, VMMCALLRING3_PGM_ALLOCATE_LARGE_HANDY_PAGE, GCPhysBase);
-#endif
+# endif
                 if (RT_SUCCESS(rc))
                 {   
@@ -550,4 +551,5 @@
     return VERR_PGM_INVALID_LARGE_PAGE_RANGE;
 }
+#endif /* PGM_WITH_LARGE_PAGES */
 
 /**
Index: trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp	(revision 27005)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp	(revision 27026)
@@ -3110,4 +3110,66 @@
         }
 
+#ifdef PGM_WITH_LARGE_PAGES
+        /* Large page case only. */
+        case PGMPOOLKIND_EPT_PD_FOR_PHYS:
+        {
+            Assert(HWACCMIsNestedPagingActive(pVM));
+            Assert(cRefs == 1);
+
+            const uint64_t  u64 = PGM_PAGE_GET_HCPHYS(pPhysPage) | X86_PDE4M_P | X86_PDE4M_PS;
+            PEPTPD          pPD = (PEPTPD)PGMPOOL_PAGE_2_PTR(pVM, pPage);
+            for (unsigned i = pPage->iFirstPresent; i < RT_ELEMENTS(pPD->a); i++)
+                if ((pPD->a[i].u & (EPT_PDE2M_PG_MASK | X86_PDE4M_P | X86_PDE4M_PS)) == u64)
+                {
+                    Log4(("pgmPoolTrackFlushGCPhysPTs: i=%d pde=%RX64 cRefs=%#x\n", i, pPD->a[i], cRefs));
+                    STAM_COUNTER_INC(&pPool->StatTrackFlushEntry);
+                    pPD->a[i].u = 0;
+                    cRefs--;
+                    if (!cRefs)
+                        return bRet;
+                }
+# ifdef LOG_ENABLED
+            Log(("cRefs=%d iFirstPresent=%d cPresent=%d\n", cRefs, pPage->iFirstPresent, pPage->cPresent));
+            for (unsigned i = 0; i < RT_ELEMENTS(pPD->a); i++)
+                if ((pPD->a[i].u & (EPT_PDE2M_PG_MASK | X86_PDE4M_P | X86_PDE4M_PS)) == u64)
+                {
+                    Log(("i=%d cRefs=%d\n", i, cRefs--));
+                }
+# endif
+            AssertFatalMsgFailed(("cRefs=%d iFirstPresent=%d cPresent=%d\n", cRefs, pPage->iFirstPresent, pPage->cPresent));
+            break;
+        }
+
+        /* AMD-V nested paging - @todo merge with EPT as we only check the parts that are identical. */
+        case PGMPOOLKIND_PAE_PD_PHYS:
+        {
+            Assert(HWACCMIsNestedPagingActive(pVM));
+            Assert(cRefs == 1);
+
+            const uint64_t  u64 = PGM_PAGE_GET_HCPHYS(pPhysPage) | X86_PDE4M_P | X86_PDE4M_PS;
+            PX86PD          pPD = (PX86PD)PGMPOOL_PAGE_2_PTR(pVM, pPage);
+            for (unsigned i = pPage->iFirstPresent; i < RT_ELEMENTS(pPD->a); i++)
+                if ((pPD->a[i].u & (X86_PDE2M_PAE_PG_MASK | X86_PDE4M_P | X86_PDE4M_PS)) == u64)
+                {
+                    Log4(("pgmPoolTrackFlushGCPhysPTs: i=%d pde=%RX64 cRefs=%#x\n", i, pPD->a[i], cRefs));
+                    STAM_COUNTER_INC(&pPool->StatTrackFlushEntry);
+                    pPD->a[i].u = 0;
+                    cRefs--;
+                    if (!cRefs)
+                        return bRet;
+                }
+# ifdef LOG_ENABLED
+            Log(("cRefs=%d iFirstPresent=%d cPresent=%d\n", cRefs, pPage->iFirstPresent, pPage->cPresent));
+            for (unsigned i = 0; i < RT_ELEMENTS(pPD->a); i++)
+                if ((pPD->a[i].u & (X86_PDE2M_PAE_PG_MASK | X86_PDE4M_P | X86_PDE4M_PS)) == u64)
+                {
+                    Log(("i=%d cRefs=%d\n", i, cRefs--));
+                }
+# endif
+            AssertFatalMsgFailed(("cRefs=%d iFirstPresent=%d cPresent=%d\n", cRefs, pPage->iFirstPresent, pPage->cPresent));
+            break;
+        }
+#endif /* PGM_WITH_LARGE_PAGES */
+
         default:
             AssertFatalMsgFailed(("enmKind=%d iShw=%d\n", pPage->enmKind, iShw));
@@ -3201,4 +3263,5 @@
  *
  * @param   pVM         The VM handle.
+ * @param   GCPhysPage  GC physical address of the page in question
  * @param   pPhysPage   The guest page in question.
  * @param   fFlushPTEs  Flush PTEs or allow them to be updated (e.g. in case of an RW bit change)
@@ -3207,9 +3270,44 @@
  *                      The caller MUST initialized this to @a false.
  */
-int pgmPoolTrackUpdateGCPhys(PVM pVM, PPGMPAGE pPhysPage, bool fFlushPTEs, bool *pfFlushTLBs)
+int pgmPoolTrackUpdateGCPhys(PVM pVM, RTGCPHYS GCPhysPage, PPGMPAGE pPhysPage, bool fFlushPTEs, bool *pfFlushTLBs)
 {
     PVMCPU pVCpu = VMMGetCpu(pVM);
     pgmLock(pVM);
     int rc = VINF_SUCCESS;
+
+#ifdef PGM_WITH_LARGE_PAGES
+    /* Is this page part of a large page? */
+    if (PGM_PAGE_GET_PDE_TYPE(pPhysPage) == PGM_PAGE_PDE_TYPE_PDE)
+    {
+        PPGMPAGE pPhysBase;
+        RTGCPHYS GCPhysBase = GCPhysPage & X86_PDE2M_PAE_PG_MASK;
+
+        GCPhysPage &= X86_PDE_PAE_PG_MASK;
+
+        /* Fetch the large page base. */
+        if (GCPhysBase != GCPhysPage)
+        {
+            pPhysBase = pgmPhysGetPage(&pVM->pgm.s, GCPhysBase);
+            AssertFatal(pPhysBase);
+        }
+        else
+            pPhysBase = pPhysPage;
+
+        Log(("pgmPoolTrackUpdateGCPhys: update large page PDE for %RGp (%RGp)\n", GCPhysBase, GCPhysPage));
+
+        /* Mark the large page as disabled as we need to break it up to change a single page in the 2 MB range. */
+        PGM_PAGE_SET_PDE_TYPE(pPhysBase, PGM_PAGE_PDE_TYPE_PDE_DISABLED);
+
+        /* Update the base as that *only* that one has a reference and there's only one PDE to clear. */
+        rc = pgmPoolTrackUpdateGCPhys(pVM, GCPhysBase, pPhysBase, fFlushPTEs, pfFlushTLBs);
+
+        *pfFlushTLBs = true;
+        pgmUnlock(pVM);
+        return rc;
+    }
+#else
+    NOREF(GCPhysPage);
+#endif /* PGM_WITH_LARGE_PAGES */
+
     const uint16_t u16 = PGM_PAGE_GET_TRACKING(pPhysPage);
     if (u16)
