Index: /trunk/src/VBox/VMM/Makefile.kmk
===================================================================
--- /trunk/src/VBox/VMM/Makefile.kmk	(revision 29467)
+++ /trunk/src/VBox/VMM/Makefile.kmk	(revision 29468)
@@ -460,4 +460,5 @@
 	VMMR0/PDMR0Driver.cpp \
 	VMMR0/PGMR0.cpp \
+	VMMR0/PGMR0SharedPage.cpp \
 	VMMR0/TRPMR0.cpp \
 	VMMR0/TRPMR0A.asm \
Index: /trunk/src/VBox/VMM/PGMSharedPage.cpp
===================================================================
--- /trunk/src/VBox/VMM/PGMSharedPage.cpp	(revision 29467)
+++ /trunk/src/VBox/VMM/PGMSharedPage.cpp	(revision 29468)
@@ -20,5 +20,5 @@
 *   Header Files                                                               *
 *******************************************************************************/
-#define LOG_GROUP LOG_GROUP_PGM_PHYS
+#define LOG_GROUP LOG_GROUP_PGM_SHARED
 #include <VBox/pgm.h>
 #include <VBox/stam.h>
Index: /trunk/src/VBox/VMM/VMMR0/PGMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/PGMR0.cpp	(revision 29467)
+++ /trunk/src/VBox/VMM/VMMR0/PGMR0.cpp	(revision 29468)
@@ -302,218 +302,2 @@
 }
 
-#ifdef VBOX_WITH_PAGE_SHARING
-/**
- * Check a registered module for shared page changes
- *
- * @returns The following VBox status codes.
- *
- * @param   pVM         The VM handle.
- * @param   idCpu       VCPU id
- * @param   pModule     Module description
- * @param   pGVM        Pointer to the GVM instance data.
- */
-VMMR0DECL(int) PGMR0SharedModuleCheckRegion(PVM pVM, VMCPUID idCpu, PGMMSHAREDMODULE pModule, PGVM pGVM)
-{
-    int                rc = VINF_SUCCESS;
-    PGMMSHAREDPAGEDESC paPageDesc = NULL;
-    uint32_t           cbPreviousRegion  = 0;
-    bool               fFlushTLBs = false;
-    PVMCPU             pVCpu = &pVM->aCpus[idCpu];
-
-    Log(("PGMR0SharedModuleCheck: check %s %s base=%RGv size=%x\n", pModule->szName, pModule->szVersion, pModule->Core.Key, pModule->cbModule));
-
-    pgmLock(pVM);
-
-    /* Check every region of the shared module. */
-    for (unsigned i = 0; i < pModule->cRegions; i++)
-    {
-        Assert((pModule->aRegions[i].cbRegion & 0xfff) == 0);
-        Assert((pModule->aRegions[i].GCRegionAddr & 0xfff) == 0);
-
-        RTGCPTR  GCRegion  = pModule->aRegions[i].GCRegionAddr;
-        unsigned cbRegion = pModule->aRegions[i].cbRegion & ~0xfff;
-        unsigned idxPage = 0;
-        bool     fValidChanges = false;
-
-        if (cbPreviousRegion < cbRegion)
-        {
-            if (paPageDesc)
-                RTMemFree(paPageDesc);
-
-            paPageDesc = (PGMMSHAREDPAGEDESC)RTMemAlloc((cbRegion >> PAGE_SHIFT) * sizeof(*paPageDesc));
-            if (!paPageDesc)
-            {
-                AssertFailed();
-                rc = VERR_NO_MEMORY;
-                goto end;
-            }
-            cbPreviousRegion  = cbRegion;
-        }
-
-        while (cbRegion)
-        {
-            RTGCPHYS GCPhys;
-            uint64_t fFlags;
-
-            rc = PGMGstGetPage(pVCpu, GCRegion, &fFlags, &GCPhys);
-            if (    rc == VINF_SUCCESS
-                &&  !(fFlags & X86_PTE_RW)) /* important as we make assumptions about this below! */
-            {
-                PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
-                if (    pPage
-                    &&  !PGM_PAGE_IS_SHARED(pPage))
-                {
-                    fValidChanges = true;
-                    paPageDesc[idxPage].uHCPhysPageId = PGM_PAGE_GET_PAGEID(pPage);
-                    paPageDesc[idxPage].HCPhys        = PGM_PAGE_GET_HCPHYS(pPage);
-                    paPageDesc[idxPage].GCPhys        = GCPhys;
-                }
-                else
-                    paPageDesc[idxPage].uHCPhysPageId = NIL_GMM_PAGEID;
-            }
-            else
-                paPageDesc[idxPage].uHCPhysPageId = NIL_GMM_PAGEID;
-
-            idxPage++;
-            GCRegion += PAGE_SIZE;
-            cbRegion -= PAGE_SIZE;
-        }
-
-        if (fValidChanges)
-        {
-            rc = GMMR0SharedModuleCheckRange(pGVM, pModule, i, idxPage, paPageDesc);
-            AssertRC(rc);
-            if (RT_FAILURE(rc))
-                break;
-                
-            for (unsigned i = 0; i < idxPage; i++)
-            {
-                /* Any change for this page? */
-                if (paPageDesc[i].uHCPhysPageId != NIL_GMM_PAGEID)
-                {
-                    /** todo: maybe cache these to prevent the nth lookup. */
-                    PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, paPageDesc[i].GCPhys);
-                    if (!pPage)
-                    {
-                        /* Should never happen. */
-                        AssertFailed();
-                        rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
-                        goto end;
-                    }
-                    Assert(!PGM_PAGE_IS_SHARED(pPage));
-
-                    Log(("PGMR0SharedModuleCheck: shared page gc phys %RGp host %RHp->%RHp\n", paPageDesc[i].GCPhys, PGM_PAGE_GET_HCPHYS(pPage), paPageDesc[i].HCPhys));
-                    if (paPageDesc[i].HCPhys != PGM_PAGE_GET_HCPHYS(pPage))
-                    {
-                        bool fFlush = false;
-
-                        /* Page was replaced by an existing shared version of it; clear all references first. */
-                        rc = pgmPoolTrackUpdateGCPhys(pVM, paPageDesc[i].GCPhys, pPage, true /* clear the entries */, &fFlush);
-                        if (RT_FAILURE(rc))
-                        {
-                            AssertRC(rc);
-                            goto end;
-                        }
-                        Assert(rc == VINF_SUCCESS || (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3) && (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_CLEAR_PGM_POOL)));
-                        if (rc = VINF_SUCCESS)
-                            fFlushTLBs |= fFlush;
-
-                        /* Update the physical address and page id now. */
-                        PGM_PAGE_SET_HCPHYS(pPage, paPageDesc[i].HCPhys);
-                        PGM_PAGE_SET_PAGEID(pPage, paPageDesc[i].uHCPhysPageId);
-
-                        /* Invalidate page map TLB entry for this page too. */
-                        PGMPhysInvalidatePageMapTLBEntry(pVM, paPageDesc[i].GCPhys);
-                    }
-                    /* else nothing changed (== this page is now a shared page), so no need to flush anything. */
-
-                    pVM->pgm.s.cSharedPages++;
-                    pVM->pgm.s.cPrivatePages--;
-                    PGM_PAGE_SET_STATE(pPage, PGM_PAGE_STATE_SHARED);
-                }
-            }
-        }
-        else
-            rc = VINF_SUCCESS;  /* nothing to do. */
-    }
-
-end:
-    pgmUnlock(pVM);
-    if (fFlushTLBs)
-        PGM_INVL_ALL_VCPU_TLBS(pVM);
-
-    if (paPageDesc)
-        RTMemFree(paPageDesc);
-
-    return rc;
-}
-#endif
-
-#if 0
-/**
- * Shared module registration helper (called on the way out).
- *
- * @param   pVM         The VM handle.
- * @param   pReq        Registration request info
- */
-static DECLCALLBACK(void) pgmR3SharedModuleRegisterHelper(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq)
-{
-    int rc;
-    
-    rc = GMMR3RegisterSharedModule(pVM, pReq);
-    Assert(rc == VINF_SUCCESS || rc == VINF_PGM_SHARED_MODULE_COLLISION || rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED);
-    if (rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED)
-    {
-        PVMCPU   pVCpu = VMMGetCpu(pVM);
-        unsigned cFlushedPages = 0;
-
-        /** todo count copy-on-write actions in the trap handler so we don't have to check everything all the time! */
-
-        /* Count the number of shared pages that were changed (copy-on-write). */
-        for (unsigned i = 0; i < pReq->cRegions; i++)
-        {
-            Assert((pReq->aRegions[i].cbRegion & 0xfff) == 0);
-            Assert((pReq->aRegions[i].GCRegionAddr & 0xfff) == 0);
-
-            RTGCPTR GCRegion  = pReq->aRegions[i].GCRegionAddr;
-            uint32_t cbRegion = pReq->aRegions[i].cbRegion & ~0xfff;
-
-            while (cbRegion)
-            {
-                RTGCPHYS GCPhys;
-                uint64_t fFlags;
-
-                rc = PGMGstGetPage(pVCpu, GCRegion, &fFlags, &GCPhys);
-                if (    rc == VINF_SUCCESS
-                    &&  !(fFlags & X86_PTE_RW))
-                {
-                    PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
-                    if (    pPage
-                        &&  !PGM_PAGE_IS_SHARED(pPage))
-                    {
-                        cFlushedPages++;
-                    }
-                }
-
-                GCRegion += PAGE_SIZE;
-                cbRegion -= PAGE_SIZE;
-            }
-        }
-
-        if (cFlushedPages > 32)
-            rc = VINF_SUCCESS;  /* force recheck below */
-    }
-    /* Full (re)check needed? */
-    if (rc == VINF_SUCCESS)
-    {
-        pReq->Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
-        pReq->Hdr.cbReq = RT_OFFSETOF(GMMREGISTERSHAREDMODULEREQ, aRegions[pReq->cRegions]);
-
-        /* We must stall other VCPUs as we'd otherwise have to send IPI flush commands for every single change we make. */
-        rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, pgmR3SharedModuleRegRendezvous, pReq);
-        AssertRC(rc);
-    }
-    RTMemFree(pReq);
-    return;
-}
-#endif
Index: /trunk/src/VBox/VMM/VMMR0/PGMR0SharedPage.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/PGMR0SharedPage.cpp	(revision 29468)
+++ /trunk/src/VBox/VMM/VMMR0/PGMR0SharedPage.cpp	(revision 29468)
@@ -0,0 +1,180 @@
+/* $Id: PGMR0.cpp 61539 2010-05-12 15:11:09Z sandervl $ */
+/** @file
+ * PGM - Page Manager and Monitor, Ring-0.
+ */
+
+/*
+ * Copyright (C) 2007 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define LOG_GROUP LOG_GROUP_PGM_SHARED
+#include <VBox/pgm.h>
+#include <VBox/gmm.h>
+#include "../PGMInternal.h"
+#include <VBox/vm.h>
+#include "../PGMInline.h"
+#include <VBox/log.h>
+#include <VBox/err.h>
+#include <iprt/assert.h>
+#include <iprt/mem.h>
+
+
+#ifdef VBOX_WITH_PAGE_SHARING
+/**
+ * Check a registered module for shared page changes
+ *
+ * @returns The following VBox status codes.
+ *
+ * @param   pVM         The VM handle.
+ * @param   idCpu       VCPU id
+ * @param   pModule     Module description
+ * @param   pGVM        Pointer to the GVM instance data.
+ */
+VMMR0DECL(int) PGMR0SharedModuleCheckRegion(PVM pVM, VMCPUID idCpu, PGMMSHAREDMODULE pModule, PGVM pGVM)
+{
+    int                rc = VINF_SUCCESS;
+    PGMMSHAREDPAGEDESC paPageDesc = NULL;
+    uint32_t           cbPreviousRegion  = 0;
+    bool               fFlushTLBs = false;
+    PVMCPU             pVCpu = &pVM->aCpus[idCpu];
+
+    Log(("PGMR0SharedModuleCheck: check %s %s base=%RGv size=%x\n", pModule->szName, pModule->szVersion, pModule->Core.Key, pModule->cbModule));
+
+    pgmLock(pVM);
+
+    /* Check every region of the shared module. */
+    for (unsigned i = 0; i < pModule->cRegions; i++)
+    {
+        Assert((pModule->aRegions[i].cbRegion & 0xfff) == 0);
+        Assert((pModule->aRegions[i].GCRegionAddr & 0xfff) == 0);
+
+        RTGCPTR  GCRegion  = pModule->aRegions[i].GCRegionAddr;
+        unsigned cbRegion = pModule->aRegions[i].cbRegion & ~0xfff;
+        unsigned idxPage = 0;
+        bool     fValidChanges = false;
+
+        if (cbPreviousRegion < cbRegion)
+        {
+            if (paPageDesc)
+                RTMemFree(paPageDesc);
+
+            paPageDesc = (PGMMSHAREDPAGEDESC)RTMemAlloc((cbRegion >> PAGE_SHIFT) * sizeof(*paPageDesc));
+            if (!paPageDesc)
+            {
+                AssertFailed();
+                rc = VERR_NO_MEMORY;
+                goto end;
+            }
+            cbPreviousRegion  = cbRegion;
+        }
+
+        while (cbRegion)
+        {
+            RTGCPHYS GCPhys;
+            uint64_t fFlags;
+
+            rc = PGMGstGetPage(pVCpu, GCRegion, &fFlags, &GCPhys);
+            if (    rc == VINF_SUCCESS
+                &&  !(fFlags & X86_PTE_RW)) /* important as we make assumptions about this below! */
+            {
+                PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
+                if (    pPage
+                    &&  !PGM_PAGE_IS_SHARED(pPage))
+                {
+                    fValidChanges = true;
+                    paPageDesc[idxPage].uHCPhysPageId = PGM_PAGE_GET_PAGEID(pPage);
+                    paPageDesc[idxPage].HCPhys        = PGM_PAGE_GET_HCPHYS(pPage);
+                    paPageDesc[idxPage].GCPhys        = GCPhys;
+                }
+                else
+                    paPageDesc[idxPage].uHCPhysPageId = NIL_GMM_PAGEID;
+            }
+            else
+                paPageDesc[idxPage].uHCPhysPageId = NIL_GMM_PAGEID;
+
+            idxPage++;
+            GCRegion += PAGE_SIZE;
+            cbRegion -= PAGE_SIZE;
+        }
+
+        if (fValidChanges)
+        {
+            rc = GMMR0SharedModuleCheckRange(pGVM, pModule, i, idxPage, paPageDesc);
+            AssertRC(rc);
+            if (RT_FAILURE(rc))
+                break;
+                
+            for (unsigned i = 0; i < idxPage; i++)
+            {
+                /* Any change for this page? */
+                if (paPageDesc[i].uHCPhysPageId != NIL_GMM_PAGEID)
+                {
+                    /** todo: maybe cache these to prevent the nth lookup. */
+                    PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, paPageDesc[i].GCPhys);
+                    if (!pPage)
+                    {
+                        /* Should never happen. */
+                        AssertFailed();
+                        rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
+                        goto end;
+                    }
+                    Assert(!PGM_PAGE_IS_SHARED(pPage));
+
+                    Log(("PGMR0SharedModuleCheck: shared page gc phys %RGp host %RHp->%RHp\n", paPageDesc[i].GCPhys, PGM_PAGE_GET_HCPHYS(pPage), paPageDesc[i].HCPhys));
+                    if (paPageDesc[i].HCPhys != PGM_PAGE_GET_HCPHYS(pPage))
+                    {
+                        bool fFlush = false;
+
+                        /* Page was replaced by an existing shared version of it; clear all references first. */
+                        rc = pgmPoolTrackUpdateGCPhys(pVM, paPageDesc[i].GCPhys, pPage, true /* clear the entries */, &fFlush);
+                        if (RT_FAILURE(rc))
+                        {
+                            AssertRC(rc);
+                            goto end;
+                        }
+                        Assert(rc == VINF_SUCCESS || (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3) && (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_CLEAR_PGM_POOL)));
+                        if (rc = VINF_SUCCESS)
+                            fFlushTLBs |= fFlush;
+
+                        /* Update the physical address and page id now. */
+                        PGM_PAGE_SET_HCPHYS(pPage, paPageDesc[i].HCPhys);
+                        PGM_PAGE_SET_PAGEID(pPage, paPageDesc[i].uHCPhysPageId);
+
+                        /* Invalidate page map TLB entry for this page too. */
+                        PGMPhysInvalidatePageMapTLBEntry(pVM, paPageDesc[i].GCPhys);
+                    }
+                    /* else nothing changed (== this page is now a shared page), so no need to flush anything. */
+
+                    pVM->pgm.s.cSharedPages++;
+                    pVM->pgm.s.cPrivatePages--;
+                    PGM_PAGE_SET_STATE(pPage, PGM_PAGE_STATE_SHARED);
+                }
+            }
+        }
+        else
+            rc = VINF_SUCCESS;  /* nothing to do. */
+    }
+
+end:
+    pgmUnlock(pVM);
+    if (fFlushTLBs)
+        PGM_INVL_ALL_VCPU_TLBS(pVM);
+
+    if (paPageDesc)
+        RTMemFree(paPageDesc);
+
+    return rc;
+}
+#endif
+
