Index: trunk/src/VBox/VMM/VMMAll/EMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 13232)
+++ trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 13235)
@@ -1786,16 +1786,15 @@
      */
 #ifdef IN_GC
-    // Note: we could also use PGMFlushPage here, but it currently doesn't always use invlpg!!!!!!!!!!
-    LogFlow(("GC: EMULATE: invlpg %08X\n", pAddrGC));
-    rc = PGMGCInvalidatePage(pVM, pAddrGC);
-#else
+    LogFlow(("RC: EMULATE: invlpg %RGv\n", pAddrGC));
+#endif
     rc = PGMInvalidatePage(pVM, pAddrGC);
-#endif
-    if (VBOX_SUCCESS(rc))
+    if (    rc == VINF_SUCCESS
+        ||  rc == VINF_PGM_SYNC_CR3 /* we can rely on the FF */)
         return VINF_SUCCESS;
-    Log(("PGMInvalidatePage %VGv returned %VGv (%d)\n", pAddrGC, rc, rc));
-    Assert(rc == VERR_REM_FLUSHED_PAGES_OVERFLOW);
-    /** @todo r=bird: we shouldn't ignore returns codes like this... I'm 99% sure the error is fatal. */
-    return VERR_EM_INTERPRETER;
+    AssertMsgReturn(   rc == VERR_REM_FLUSHED_PAGES_OVERFLOW
+                    || rc == VINF_EM_RAW_EMULATE_INSTR,
+                    ("%Rrc addr=%RGv\n", rc, pAddrGC),
+                    VERR_EM_INTERPRETER);
+    return rc;
 }
 
@@ -1830,14 +1829,15 @@
      */
 #ifdef IN_GC
-    // Note: we could also use PGMFlushPage here, but it currently doesn't always use invlpg!!!!!!!!!!
-    LogFlow(("GC: EMULATE: invlpg %08X\n", addr));
-    rc = PGMGCInvalidatePage(pVM, addr);
-#else
+    LogFlow(("RC: EMULATE: invlpg %RGv\n", addr));
+#endif
     rc = PGMInvalidatePage(pVM, addr);
-#endif
-    if (VBOX_SUCCESS(rc))
+    if (    rc == VINF_SUCCESS
+        ||  rc == VINF_PGM_SYNC_CR3 /* we can rely on the FF */)
         return VINF_SUCCESS;
-    /** @todo r=bird: we shouldn't ignore returns codes like this... I'm 99% sure the error is fatal. */
-    return VERR_EM_INTERPRETER;
+    AssertMsgReturn(   rc == VERR_REM_FLUSHED_PAGES_OVERFLOW
+                    || rc == VINF_EM_RAW_EMULATE_INSTR,
+                    ("%Rrc addr=%RGv\n", rc, addr),
+                    VERR_EM_INTERPRETER);
+    return rc;
 }
 
Index: trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 13232)
+++ trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 13235)
@@ -624,13 +624,18 @@
 
 
-#ifndef IN_GC
 /**
  * Emulation of the invlpg instruction (HC only actually).
  *
- * @returns VBox status code.
+ * @returns VBox status code, special care required.
+ * @retval  VINF_PGM_SYNC_CR3 - handled.
+ * @retval  VINF_EM_RAW_EMULATE_INSTR - not handled (RC only).
+ * @retval  VERR_REM_FLUSHED_PAGES_OVERFLOW - not handled.
+ *
  * @param   pVM         VM handle.
  * @param   GCPtrPage   Page to invalidate.
- * @remark  ASSUMES the page table entry or page directory is
- *          valid. Fairly safe, but there could be edge cases!
+ *
+ * @remark  ASSUMES the page table entry or page directory is valid. Fairly
+ *          safe, but there could be edge cases!
+ *
  * @todo    Flush page or page directory only if necessary!
  */
@@ -638,10 +643,7 @@
 {
     int rc;
-
     Log3(("PGMInvalidatePage: GCPtrPage=%VGv\n", GCPtrPage));
 
-    /** @todo merge PGMGCInvalidatePage with this one */
-
-# ifndef IN_RING3
+#ifndef IN_RING3
     /*
      * Notify the recompiler so it can record this instruction.
@@ -649,13 +651,41 @@
      */
     rc = REMNotifyInvalidatePage(pVM, GCPtrPage);
-    if (VBOX_FAILURE(rc))
+    if (rc != VINF_SUCCESS)
         return rc;
-# endif
-
+#endif /* !IN_RING3 */
+
+
+#ifdef IN_GC
+    /*
+     * Check for conflicts and pending CR3 monitoring updates.
+     */
+    if (!pVM->pgm.s.fMappingsFixed)
+    {
+        if (    pgmGetMapping(pVM, GCPtrPage)
+            &&  PGMGstGetPage(pVM, GCPtrPage, NULL, NULL) != VERR_PAGE_TABLE_NOT_PRESENT)
+        {
+            LogFlow(("PGMGCInvalidatePage: Conflict!\n"));
+            VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
+            STAM_COUNTER_INC(&pVM->pgm.s.StatRCInvlPgConflict);
+            return VINF_PGM_SYNC_CR3;
+        }
+
+        if (pVM->pgm.s.fSyncFlags & PGM_SYNC_MONITOR_CR3)
+        {
+            LogFlow(("PGMGCInvalidatePage: PGM_SYNC_MONITOR_CR3 -> reinterpret instruction in R3\n"));
+            STAM_COUNTER_INC(&pVM->pgm.s.StatRCInvlPgSyncMonCR3);
+            return VINF_EM_RAW_EMULATE_INSTR;
+        }
+    }
+#endif /* IN_GC */
+
+    /*
+     * Call paging mode specific worker.
+     */
     STAM_PROFILE_START(&pVM->pgm.s.CTX_MID_Z(Stat,InvalidatePage), a);
     rc = PGM_BTH_PFN(InvalidatePage, pVM)(pVM, GCPtrPage);
     STAM_PROFILE_STOP(&pVM->pgm.s.CTX_MID_Z(Stat,InvalidatePage), a);
 
-# ifndef IN_RING0
+#ifdef IN_RING3
     /*
      * Check if we have a pending update of the CR3 monitoring.
@@ -669,16 +699,15 @@
         rc = PGM_GST_PFN(MonitorCR3, pVM)(pVM, pVM->pgm.s.GCPhysCR3);
     }
-# endif
-
-# ifdef IN_RING3
+
     /*
      * Inform CSAM about the flush
-     */
-    /* note: This is to check if monitored pages have been changed; when we implement callbacks for virtual handlers, this is no longer required. */
+     *
+     * Note: This is to check if monitored pages have been changed; when we implement
+     *       callbacks for virtual handlers, this is no longer required.
+     */
     CSAMR3FlushPage(pVM, GCPtrPage);
-# endif
+#endif /* IN_RING3 */
     return rc;
 }
-#endif /* !IN_GC */
 
 
Index: trunk/src/VBox/VMM/VMMAll/PGMAllBth.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 13232)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 13235)
@@ -1110,6 +1110,6 @@
  	            && !(pPDEDst[iPD].u & PGM_PDFLAGS_MAPPING))
  	        {
-                pgmPoolFreeByPage(pPool, pgmPoolGetPage(pPool, pPDEDst[iPD].u & SHW_PDE_PG_MASK), SHW_POOL_ROOT_IDX, iPdpte * X86_PG_PAE_ENTRIES + iPD);
-                pPDEDst[iPD].u = 0;
+                    pgmPoolFreeByPage(pPool, pgmPoolGetPage(pPool, pPDEDst[iPD].u & SHW_PDE_PG_MASK), SHW_POOL_ROOT_IDX, iPdpte * X86_PG_PAE_ENTRIES + iPD);
+                    pPDEDst[iPD].u = 0;
  	        }
 	    }
