Index: trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp	(revision 45797)
+++ trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp	(revision 45798)
@@ -675,4 +675,10 @@
     pVCpu->cpum.s.fChanged |= CPUM_CHANGED_CR0;
 
+    /*
+     * Let PGM know if the WP goes from 0 to 1 (netware WP0+RO+US hack)
+     */
+    if (((cr0 ^ pVCpu->cpum.s.Guest.cr0) & X86_CR0_WP) && (cr0 & X86_CR0_WP))
+        PGMCr0WpEnabled(pVCpu);
+
     pVCpu->cpum.s.Guest.cr0 = cr0 | X86_CR0_ET;
     return VINF_SUCCESS;
Index: trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 45797)
+++ trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 45798)
@@ -2207,4 +2207,32 @@
 
 /**
+ * Called by CPUM or REM when CR0.WP changes to 1.
+ *
+ * @param   pVCpu       The cross context virtual CPU structure of the caller.
+ * @thread  EMT
+ */
+VMM_INT_DECL(void) PGMCr0WpEnabled(PVMCPU pVCpu)
+{
+    /*
+     * Netware WP0+RO+US hack cleanup when WP0 -> WP1.
+     *
+     * Use the counter to judge whether there might be pool pages with active
+     * hacks in them.  If there are, we will be running the risk of messing up
+     * the guest by allowing it to write to read-only pages.  Thus, we have to
+     * clear the page pool ASAP if there is the slightest chance.
+     */
+    if (pVCpu->pgm.s.cNetwareWp0Hacks > 0)
+    {
+        Assert(pVCpu->CTX_SUFF(pVM)->cCpus == 1);
+
+        Log(("PGMCr0WpEnabled: %llu WP0 hacks active - clearing page pool\n", pVCpu->pgm.s.cNetwareWp0Hacks));
+        pVCpu->pgm.s.cNetwareWp0Hacks = 0;
+        pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_CLEAR_PGM_POOL;
+        VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
+    }
+}
+
+
+/**
  * Gets the current guest paging mode.
  *
Index: trunk/src/VBox/VMM/VMMAll/PGMAllBth.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 45797)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 45798)
@@ -987,7 +987,20 @@
             {
                 Assert((uErr & (X86_TRAP_PF_RW | X86_TRAP_PF_P)) == (X86_TRAP_PF_RW | X86_TRAP_PF_P));
-#    ifdef PGM_WITH_NETWARE_WP0_HACK
+
+                /*
+                 * The Netware WP0+RO+US hack.
+                 *
+                 * Netware sometimes(/always?) runs with WP0.  It has been observed doing
+                 * accessive write accesses to pages which are mapped with US=1 and RW=0
+                 * while WP=0.  This causes a lot of exits and extremely slow execution.
+                 * To avoid trapping and emulating every write here, we change the shadow
+                 * page table entry to map it as US=0 and RW=1 until user mode tries to
+                 * access it again (see further below).  We count these shadow page table
+                 * changes so we can avoid having to clear the page pool every time the WP
+                 * bit changes to 1 (see PGMCr0WpEnabled()).
+                 */
                 if (   GstWalk.Core.fEffectiveUS
-                    && !GstWalk.Core.fBigPage)
+                    && !GstWalk.Core.fBigPage
+                    && pVM->cCpus == 1 /* Sorry, no go on SMP. Add CFGM option? */)
                 {
                     /* Temorarily change the page to a RW super visor page. We'll trap
@@ -996,14 +1009,18 @@
                     Log(("PGM #PF: Netware WP0+RO+US hack: pvFault=%RGp uErr=%#x\n", pvFault, uErr));
                     rc = pgmShwMakePageSupervisorAndWritable(pVCpu, pvFault, PGM_MK_PG_IS_WRITE_FAULT);
-                    PGM_INVL_PG(pVCpu, pvFault);
                     if (rc == VINF_SUCCESS || rc == VINF_PGM_SYNC_CR3)
                     {
-                        STAM_STATS({ pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eTime2WPEmulation; });  /**< @todo New stat. */
+                        PGM_INVL_PG(pVCpu, pvFault);
+                        pVCpu->pgm.s.cNetwareWp0Hacks++;
+                        STAM_STATS({ pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eTime2Wp0RoUsHack; });
                         return rc;
                     }
+                    AssertMsg(RT_FAILURE_NP(rc), ("%Rrc\n", rc));
                     Log(("pgmShwMakePageSupervisorAndWritable(%RGv) failed with rc=%Rrc - ignored\n", pvFault, rc));
                 }
-#    endif
+
+                /* Interpret the access. */
                 rc = VBOXSTRICTRC_TODO(PGMInterpretInstruction(pVM, pVCpu, pRegFrame, pvFault));
+                Log(("PGM #PF: WP0 emulation (pvFault=%RGp uErr=%#x)\n", pvFault, uErr));
                 if (RT_SUCCESS(rc))
                     STAM_COUNTER_INC(&pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eWPEmulInRZ);
@@ -1060,5 +1077,5 @@
             }
         }
-#    if defined(PGM_WITH_NETWARE_WP0_HACK) && PGM_WITH_PAGING(PGM_GST_TYPE, PGM_SHW_TYPE)
+#    if PGM_WITH_PAGING(PGM_GST_TYPE, PGM_SHW_TYPE)
         /*
          * Check for Netware WP0+RO+US hack from above and undo it when user
@@ -1068,6 +1085,8 @@
                  &&  GstWalk.Core.fEffectiveUS
                  &&  GstWalk.Core.fBigPage
+                 &&  pVCpu->pgm.s.cNetwareWp0Hacks > 0
                  &&  (CPUMGetGuestCR0(pVCpu) & (X86_CR0_WP | X86_CR0_PG)) == X86_CR0_PG
                  &&  CPUMGetGuestCPL(pVCpu) == 3
+                 &&  pVM->cCpus == 1
                 )
         {
@@ -1077,9 +1096,10 @@
             {
                 PGM_INVL_PG(pVCpu, pvFault);
-                STAM_STATS({ pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eTime2WPEmulation; }); /**< @todo New stat. */
+                pVCpu->pgm.s.cNetwareWp0Hacks--;
+                STAM_STATS({ pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eTime2Wp0RoUsUnhack; });
                 return VINF_SUCCESS;
             }
         }
-#    endif
+#    endif /* PGM_WITH_PAGING */
 
         /** @todo else: why are we here? */
Index: trunk/src/VBox/VMM/VMMAll/PGMAllShw.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllShw.h	(revision 45797)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllShw.h	(revision 45798)
@@ -461,5 +461,5 @@
                     if (RT_SUCCESS(rc))
                     {
-                        Assert(fGstPte & X86_PTE_RW);
+                        Assert((fGstPte & X86_PTE_RW) || !(CPUMGetGuestCR0(pVCpu) & X86_CR0_WP /* allow netware hack */));
                         PPGMPAGE pPage = pgmPhysGetPage(pVM, GCPhys);
                         Assert(pPage);
Index: trunk/src/VBox/VMM/VMMR3/PGM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/PGM.cpp	(revision 45797)
+++ trunk/src/VBox/VMM/VMMR3/PGM.cpp	(revision 45798)
@@ -1892,4 +1892,6 @@
         PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2SyncPT,           "/PGM/CPU%u/RZ/Trap0e/Time2/SyncPT",            "Profiling of the Trap0eHandler body when the cause is lazy syncing of a PT.");
         PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2WPEmulation,      "/PGM/CPU%u/RZ/Trap0e/Time2/WPEmulation",       "Profiling of the Trap0eHandler body when the cause is CR0.WP emulation.");
+        PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2Wp0RoUsHack,      "/PGM/CPU%u/RZ/Trap0e/Time2/WP0R0USHack",       "Profiling of the Trap0eHandler body when the cause is CR0.WP and netware hack to be enabled.");
+        PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2Wp0RoUsUnhack,    "/PGM/CPU%u/RZ/Trap0e/Time2/WP0R0USUnhack",     "Profiling of the Trap0eHandler body when the cause is CR0.WP and netware hack to be disabled.");
         PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eConflicts,             "/PGM/CPU%u/RZ/Trap0e/Conflicts",               "The number of times #PF was caused by an undetected conflict.");
         PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersMapping,       "/PGM/CPU%u/RZ/Trap0e/Handlers/Mapping",        "Number of traps due to access handlers in mappings.");
Index: trunk/src/VBox/VMM/include/PGMInternal.h
===================================================================
--- trunk/src/VBox/VMM/include/PGMInternal.h	(revision 45797)
+++ trunk/src/VBox/VMM/include/PGMInternal.h	(revision 45798)
@@ -3433,4 +3433,6 @@
     STAMPROFILE StatRZTrap0eTime2SyncPT;            /**< RC/R0: Profiling of the Trap0eHandler body when the cause is lazy syncing of a PT. */
     STAMPROFILE StatRZTrap0eTime2WPEmulation;       /**< RC/R0: Profiling of the Trap0eHandler body when the cause is CR0.WP emulation. */
+    STAMPROFILE StatRZTrap0eTime2Wp0RoUsHack;       /**< RC/R0: Profiling of the Trap0eHandler body when the cause is CR0.WP and netware hack to be enabled. */
+    STAMPROFILE StatRZTrap0eTime2Wp0RoUsUnhack;     /**< RC/R0: Profiling of the Trap0eHandler body when the cause is CR0.WP and netware hack to be disabled. */
     STAMCOUNTER StatRZTrap0eConflicts;              /**< RC/R0: The number of times \#PF was caused by an undetected conflict. */
     STAMCOUNTER StatRZTrap0eHandlersMapping;        /**< RC/R0: Number of traps due to access handlers in mappings. */
@@ -3641,5 +3643,5 @@
      * This is used to queue operations for PGMSyncCR3, PGMInvalidatePage,
      * PGMFlushTLB, and PGMR3Load. */
-    RTUINT                          fSyncFlags;
+    uint32_t                        fSyncFlags;
 
     /** The shadow paging mode. */
@@ -3835,4 +3837,7 @@
      * on the stack. */
     DISCPUSTATE                     DisState;
+
+    /** Counts the number of times the netware WP0+RO+US hack has been applied. */
+    uint64_t                        cNetwareWp0Hacks;
 
     /** Count the number of pgm pool access handler calls. */
