Index: trunk/src/VBox/VMM/VMMAll/EMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 30332)
+++ trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 30338)
@@ -424,16 +424,6 @@
 DECLINLINE(int) emRamWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, RTGCPTR GCPtrDst, const void *pvSrc, uint32_t cb)
 {
-#ifdef IN_RC
-    int rc = MMGCRamWrite(pVM, (void *)(uintptr_t)GCPtrDst, (void *)pvSrc, cb);
-    if (RT_LIKELY(rc != VERR_ACCESS_DENIED))
-        return rc;
-    /*
-     * The page pool cache may end up here in some cases because it
-     * flushed one of the shadow mappings used by the trapping
-     * instruction and it either flushed the TLB or the CPU reused it.
-     * We want to play safe here, verifying that we've got write
-     * access doesn't cost us much (see PGMPhysGCPtr2GCPhys()).
-     */
-#endif
+    /* Don't use MMGCRamWrite here as it does not respect zero pages, shared
+       pages or write monitored pages. */
     return PGMPhysInterpretedWriteNoHandlers(pVCpu, pCtxCore, GCPtrDst, pvSrc, cb, /*fMayTrap*/ false);
 }
@@ -933,11 +923,7 @@
     RTGCPTR GCPtrPar1 = param1.val.val64;
     GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->param1, GCPtrPar1);
-#ifdef IN_RC
-    pvParam1  = (void *)(uintptr_t)GCPtrPar1;
-#else
     PGMPAGEMAPLOCK Lock;
     rc = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrPar1, &pvParam1, &Lock);
     AssertRCReturn(rc, VERR_EM_INTERPRETER);
-#endif
 
     /* Try emulate it with a one-shot #PF handler in place. (RC) */
@@ -945,13 +931,6 @@
 
     RTGCUINTREG32 eflags = 0;
-#ifdef IN_RC
-    MMGCRamRegisterTrapHandler(pVM);
-#endif
     rc = pfnEmulate(pvParam1, ValPar2, pDis->param2.size, &eflags);
-#ifdef IN_RC
-    MMGCRamDeregisterTrapHandler(pVM);
-#else
     PGMPhysReleasePageMappingLock(pVM, &Lock);
-#endif
     if (RT_FAILURE(rc))
     {
@@ -1189,11 +1168,7 @@
 #endif
 
-#ifdef IN_RC
-    pvParam1  = (void *)(uintptr_t)GCPtrPar1;
-#else
     PGMPAGEMAPLOCK Lock;
     rc = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrPar1, &pvParam1, &Lock);
     AssertRCReturn(rc, VERR_EM_INTERPRETER);
-#endif
 
     Log2(("emInterpretLockBitTest %s: pvFault=%RGv GCPtrPar1=%RGv imm=%RX64\n", emGetMnemonic(pDis), pvFault, GCPtrPar1, ValPar2));
@@ -1201,13 +1176,6 @@
     /* Try emulate it with a one-shot #PF handler in place. (RC) */
     RTGCUINTREG32 eflags = 0;
-#ifdef IN_RC
-    MMGCRamRegisterTrapHandler(pVM);
-#endif
     rc = pfnEmulate(pvParam1, ValPar2, &eflags);
-#ifdef IN_RC
-    MMGCRamDeregisterTrapHandler(pVM);
-#else
     PGMPhysReleasePageMappingLock(pVM, &Lock);
-#endif
     if (RT_FAILURE(rc))
     {
@@ -1514,5 +1482,4 @@
 #endif /* !IN_RC */
 
-#ifndef IN_RC
 
 /**
@@ -1637,13 +1604,15 @@
 }
 
-#else /* IN_RC */
-
-/**
- * [LOCK] CMPXCHG emulation.
- */
-static int emInterpretCmpXchg(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
+
+#ifdef IN_RC /** @todo test+enable for HWACCM as well. */
+/**
+ * [LOCK] XADD emulation.
+ */
+static int emInterpretXAdd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
 {
     Assert(pDis->mode != CPUMODE_64BIT);    /** @todo check */
-    OP_PARAMVAL param1, param2;
+    OP_PARAMVAL param1;
+    void *pvParamReg2;
+    size_t cbParamReg2;
 
     /* Source to make DISQueryParamVal read the register value - ugly hack */
@@ -1652,14 +1621,19 @@
         return VERR_EM_INTERPRETER;
 
-    rc = DISQueryParamVal(pRegFrame, pDis, &pDis->param2, &param2, PARAM_SOURCE);
+    rc = DISQueryParamRegPtr(pRegFrame, pDis, &pDis->param2, &pvParamReg2, &cbParamReg2);
+    Assert(cbParamReg2 <= 4);
     if(RT_FAILURE(rc))
         return VERR_EM_INTERPRETER;
 
+#ifdef IN_RC
     if (TRPMHasTrap(pVCpu))
     {
         if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
         {
-            RTRCPTR pParam1;
-            uint32_t valpar, eflags;
+#endif
+            RTGCPTR         GCPtrPar1;
+            void           *pvParam1;
+            uint32_t        eflags;
+            PGMPAGEMAPLOCK  Lock;
 
             AssertReturn(pDis->param1.size == pDis->param2.size, VERR_EM_INTERPRETER);
@@ -1667,6 +1641,11 @@
             {
             case PARMTYPE_ADDRESS:
-                pParam1 = (RTRCPTR)(uintptr_t)emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->param1, (RTRCUINTPTR)param1.val.val64);
-                EM_ASSERT_FAULT_RETURN(pParam1 == (RTRCPTR)pvFault, VERR_EM_INTERPRETER);
+                GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->param1, (RTRCUINTPTR)param1.val.val64);
+#ifdef IN_RC
+                EM_ASSERT_FAULT_RETURN(GCPtrPar1 == pvFault, VERR_EM_INTERPRETER);
+#endif
+
+                rc = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrPar1, &pvParam1, &Lock);
+                AssertRCReturn(rc, VERR_EM_INTERPRETER);
                 break;
 
@@ -1675,30 +1654,12 @@
             }
 
-            switch(param2.type)
-            {
-            case PARMTYPE_IMMEDIATE: /* register actually */
-                valpar = param2.val.val32;
-                break;
-
-            default:
-                return VERR_EM_INTERPRETER;
-            }
-
-            LogFlow(("%s %RRv eax=%08x %08x\n", emGetMnemonic(pDis), pParam1, pRegFrame->eax, valpar));
-
-            MMGCRamRegisterTrapHandler(pVM);
+            LogFlow(("XAdd %RGv=%p reg=%ll08x\n", GCPtrPar1, pvParam1, *(uint64_t *)pvParamReg2));
+
             if (pDis->prefix & PREFIX_LOCK)
-                rc = EMGCEmulateLockCmpXchg(pParam1, &pRegFrame->eax, valpar, pDis->param2.size, &eflags);
+                eflags = EMEmulateLockXAdd(pvParam1, pvParamReg2, cbParamReg2);
             else
-                rc = EMGCEmulateCmpXchg(pParam1, &pRegFrame->eax, valpar, pDis->param2.size, &eflags);
-            MMGCRamDeregisterTrapHandler(pVM);
-
-            if (RT_FAILURE(rc))
-            {
-                Log(("%s %RGv eax=%08x %08x -> emulation failed due to page fault!\n", emGetMnemonic(pDis), pParam1, pRegFrame->eax, valpar));
-                return VERR_EM_INTERPRETER;
-            }
-
-            LogFlow(("%s %RRv eax=%08x %08x ZF=%d\n", emGetMnemonic(pDis), pParam1, pRegFrame->eax, valpar, !!(eflags & X86_EFL_ZF)));
+                eflags = EMEmulateXAdd(pvParam1, pvParamReg2, cbParamReg2);
+
+            LogFlow(("XAdd %RGv=%p reg=%ll08x ZF=%d\n", GCPtrPar1, pvParam1, *(uint64_t *)pvParamReg2, !!(eflags & X86_EFL_ZF) ));
 
             /* Update guest's eflags and finish. */
@@ -1706,140 +1667,13 @@
                                   | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
 
-            *pcbSize = param2.size;
+            *pcbSize = cbParamReg2;
+            PGMPhysReleasePageMappingLock(pVM, &Lock);
             return VINF_SUCCESS;
+#ifdef IN_RC
         }
     }
+
     return VERR_EM_INTERPRETER;
-}
-
-
-/**
- * [LOCK] CMPXCHG8B emulation.
- */
-static int emInterpretCmpXchg8b(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
-{
-    Assert(pDis->mode != CPUMODE_64BIT);    /** @todo check */
-    OP_PARAMVAL param1;
-
-    /* Source to make DISQueryParamVal read the register value - ugly hack */
-    int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->param1, &param1, PARAM_SOURCE);
-    if(RT_FAILURE(rc))
-        return VERR_EM_INTERPRETER;
-
-    if (TRPMHasTrap(pVCpu))
-    {
-        if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
-        {
-            RTRCPTR pParam1;
-            uint32_t eflags;
-
-            AssertReturn(pDis->param1.size == 8, VERR_EM_INTERPRETER);
-            switch(param1.type)
-            {
-            case PARMTYPE_ADDRESS:
-                pParam1 = (RTRCPTR)(uintptr_t)emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->param1, (RTRCUINTPTR)param1.val.val64);
-                EM_ASSERT_FAULT_RETURN(pParam1 == (RTRCPTR)pvFault, VERR_EM_INTERPRETER);
-                break;
-
-            default:
-                return VERR_EM_INTERPRETER;
-            }
-
-            LogFlow(("%s %RRv=%08x eax=%08x\n", emGetMnemonic(pDis), pParam1, pRegFrame->eax));
-
-            MMGCRamRegisterTrapHandler(pVM);
-            if (pDis->prefix & PREFIX_LOCK)
-                rc = EMGCEmulateLockCmpXchg8b(pParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx, &eflags);
-            else
-                rc = EMGCEmulateCmpXchg8b(pParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx, &eflags);
-            MMGCRamDeregisterTrapHandler(pVM);
-
-            if (RT_FAILURE(rc))
-            {
-                Log(("%s %RGv=%08x eax=%08x -> emulation failed due to page fault!\n", emGetMnemonic(pDis), pParam1, pRegFrame->eax));
-                return VERR_EM_INTERPRETER;
-            }
-
-            LogFlow(("%s %RGv=%08x eax=%08x ZF=%d\n", emGetMnemonic(pDis), pParam1, pRegFrame->eax, !!(eflags & X86_EFL_ZF)));
-
-            /* Update guest's eflags and finish; note that *only* ZF is affected. */
-            pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_ZF))
-                                  | (eflags                &  (X86_EFL_ZF));
-
-            *pcbSize = 8;
-            return VINF_SUCCESS;
-        }
-    }
-    return VERR_EM_INTERPRETER;
-}
-
-#endif /* IN_RC */
-
-#ifdef IN_RC
-/**
- * [LOCK] XADD emulation.
- */
-static int emInterpretXAdd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
-{
-    Assert(pDis->mode != CPUMODE_64BIT);    /** @todo check */
-    OP_PARAMVAL param1;
-    uint32_t *pParamReg2;
-    size_t cbSizeParamReg2;
-
-    /* Source to make DISQueryParamVal read the register value - ugly hack */
-    int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->param1, &param1, PARAM_SOURCE);
-    if(RT_FAILURE(rc))
-        return VERR_EM_INTERPRETER;
-
-    rc = DISQueryParamRegPtr(pRegFrame, pDis, &pDis->param2, (void **)&pParamReg2, &cbSizeParamReg2);
-    Assert(cbSizeParamReg2 <= 4);
-    if(RT_FAILURE(rc))
-        return VERR_EM_INTERPRETER;
-
-    if (TRPMHasTrap(pVCpu))
-    {
-        if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
-        {
-            RTRCPTR pParam1;
-            uint32_t eflags;
-
-            AssertReturn(pDis->param1.size == pDis->param2.size, VERR_EM_INTERPRETER);
-            switch(param1.type)
-            {
-            case PARMTYPE_ADDRESS:
-                pParam1 = (RTRCPTR)(uintptr_t)emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->param1, (RTRCUINTPTR)param1.val.val64);
-                EM_ASSERT_FAULT_RETURN(pParam1 == (RTRCPTR)pvFault, VERR_EM_INTERPRETER);
-                break;
-
-            default:
-                return VERR_EM_INTERPRETER;
-            }
-
-            LogFlow(("XAdd %RRv=%08x reg=%08x\n", pParam1, *pParamReg2));
-
-            MMGCRamRegisterTrapHandler(pVM);
-            if (pDis->prefix & PREFIX_LOCK)
-                rc = EMGCEmulateLockXAdd(pParam1, pParamReg2, cbSizeParamReg2, &eflags);
-            else
-                rc = EMGCEmulateXAdd(pParam1, pParamReg2, cbSizeParamReg2, &eflags);
-            MMGCRamDeregisterTrapHandler(pVM);
-
-            if (RT_FAILURE(rc))
-            {
-                Log(("XAdd %RGv reg=%08x -> emulation failed due to page fault!\n", pParam1, *pParamReg2));
-                return VERR_EM_INTERPRETER;
-            }
-
-            LogFlow(("XAdd %RGv reg=%08x ZF=%d\n", pParam1, *pParamReg2, !!(eflags & X86_EFL_ZF)));
-
-            /* Update guest's eflags and finish. */
-            pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
-                                  | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
-
-            *pcbSize = cbSizeParamReg2;
-            return VINF_SUCCESS;
-        }
-    }
-    return VERR_EM_INTERPRETER;
+#endif
 }
 #endif /* IN_RC */
@@ -3193,5 +3027,6 @@
  * @copydoc EMInterpretInstructionCPU
  */
-DECLINLINE(int) emInterpretInstructionCPU(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize, EMCODETYPE enmCodeType)
+DECLINLINE(int) emInterpretInstructionCPU(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault,
+                                          uint32_t *pcbSize, EMCODETYPE enmCodeType)
 {
     Assert(enmCodeType == EMCODETYPE_SUPERVISOR || enmCodeType == EMCODETYPE_ALL);
Index: trunk/src/VBox/VMM/VMMAll/EMAllA.asm
===================================================================
--- trunk/src/VBox/VMM/VMMAll/EMAllA.asm	(revision 30332)
+++ trunk/src/VBox/VMM/VMMAll/EMAllA.asm	(revision 30338)
@@ -24,5 +24,5 @@
 
 ;; @def MY_PTR_REG
-; The register we use for value pointers (And,Or,Dec,Inc).
+; The register we use for value pointers (And,Or,Dec,Inc,XAdd).
 %ifdef RT_ARCH_AMD64
  %define MY_PTR_REG     rcx
@@ -293,13 +293,4 @@
 BITS 32
 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
-
-
-%ifdef IN_RC
-; #PF resume point.
-GLOBALNAME EMEmulateLockAnd_Error
-    mov     eax, VERR_ACCESS_DENIED
-    ret
-%endif
-
 ENDPROC     EMEmulateLockAnd
 
@@ -471,13 +462,4 @@
 BITS 32
 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
-
-
-%ifdef IN_RC
-; #PF resume point.
-GLOBALNAME EMEmulateLockOr_Error
-    mov     eax, VERR_ACCESS_DENIED
-    ret
-%endif
-
 ENDPROC     EMEmulateLockOr
 
@@ -649,13 +631,4 @@
 BITS 32
 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
-
-
-%ifdef IN_RC
-; #PF resume point.
-GLOBALNAME EMEmulateLockXor_Error
-    mov     eax, VERR_ACCESS_DENIED
-    ret
-%endif
-
 ENDPROC     EMEmulateLockXor
 
@@ -1097,12 +1070,4 @@
     mov     eax, VINF_SUCCESS
     retn
-
-%ifdef IN_RC
-; #PF resume point.
-GLOBALNAME EMEmulateLockBtr_Error
-    mov     eax, VERR_ACCESS_DENIED
-    ret
-%endif
-
 ENDPROC     EMEmulateLockBtr
 
@@ -1529,2 +1494,181 @@
 ENDPROC     EMEmulateCmpXchg8b
 
+
+;;
+; Emulate LOCK XADD instruction.
+; VMMDECL(uint32_t)   EMEmulateLockXAdd(void *pvParam1, void *pvParam2, size_t cbOp);
+;
+; @returns (eax=)eflags
+; @param    [esp + 04h]  gcc:rdi  msc:rcx  Param 1 - First parameter - pointer to data item.
+; @param    [esp + 08h]  gcc:rsi  msc:rdx  Param 2 - Second parameter - pointer to second parameter (general register)
+; @param    [esp + 0ch]  gcc:rdx  msc:r8   Param 3 - Size of parameters - {1,2,4,8}.
+;
+align 16
+BEGINPROC   EMEmulateLockXAdd
+%ifdef RT_ARCH_AMD64
+ %ifdef RT_OS_WINDOWS
+    mov     rax, r8                     ; eax = size of parameters
+ %else  ; !RT_OS_WINDOWS
+    mov     rax, rdx                    ; rax = size of parameters
+    mov     rcx, rdi                    ; rcx = first parameter
+    mov     rdx, rsi                    ; rdx = second parameter
+ %endif ; !RT_OS_WINDOWS
+%else   ; !RT_ARCH_AMD64
+    mov     eax, [esp + 0ch]            ; eax = size of parameters
+    mov     ecx, [esp + 04h]            ; ecx = first parameter
+    mov     edx, [esp + 08h]            ; edx = second parameter
+%endif
+
+    ; switch on size
+%ifdef CAN_DO_8_BYTE_OP
+    cmp     al, 8
+    je short .do_qword                  ; 8 bytes variant
+%endif
+    cmp     al, 4
+    je short .do_dword                  ; 4 bytes variant
+    cmp     al, 2
+    je short .do_word                   ; 2 byte variant
+    cmp     al, 1
+    je short .do_byte                   ; 1 bytes variant
+    int3
+
+    ; workers
+%ifdef RT_ARCH_AMD64
+.do_qword:
+    mov     rax, qword [xDX]            ; load 2nd parameter's value
+    lock xadd qword [MY_PTR_REG], rax   ; do 8 bytes XADD
+    mov     qword [xDX], rax
+    jmp     short .done
+%endif
+
+.do_dword:
+    mov     eax, dword [xDX]            ; load 2nd parameter's value
+    lock xadd dword [MY_PTR_REG], eax   ; do 4 bytes XADD
+    mov     dword [xDX], eax
+    jmp     short .done
+
+.do_word:
+    mov     eax, dword [xDX]            ; load 2nd parameter's value
+    lock xadd word [MY_PTR_REG], ax     ; do 2 bytes XADD
+    mov     word [xDX], ax
+    jmp     short .done
+
+.do_byte:
+    mov     eax, dword [xDX]            ; load 2nd parameter's value
+    lock xadd byte [MY_PTR_REG], al     ; do 1 bytes XADD
+    mov     byte [xDX], al
+
+.done:
+    ; collect flags and return.
+    pushf
+    pop     MY_RET_REG
+
+    retn
+
+%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
+.do_qword:
+    db      0xea                        ; jmp far .sixtyfourbit_mode
+    dd      .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
+BITS 64
+.sixtyfourbit_mode:
+    and     esp, 0ffffffffh
+    and     edx, 0ffffffffh
+    and     MY_PTR_REG, 0ffffffffh
+    mov     rax, qword [rdx]            ; load 2nd parameter's value
+    and     [MY_PTR_REG64], rax         ; do 8 bytes XADD
+    jmp far [.fpret wrt rip]
+.fpret:                                 ; 16:32 Pointer to .done.
+    dd      .done, NAME(SUPR0AbsKernelCS)
+BITS 32
+%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
+ENDPROC     EMEmulateLockXAdd
+
+
+;;
+; Emulate XADD instruction.
+; VMMDECL(uint32_t)   EMEmulateXAdd(void *pvParam1, void *pvParam2, size_t cbOp);
+;
+; @returns eax=eflags
+; @param    [esp + 04h]  gcc:rdi  msc:rcx  Param 1 - First parameter - pointer to data item.
+; @param    [esp + 08h]  gcc:rsi  msc:rdx  Param 2 - Second parameter - pointer to second parameter (general register)
+; @param    [esp + 0ch]  gcc:rdx  msc:r8   Param 3 - Size of parameters - {1,2,4,8}.
+align 16
+BEGINPROC   EMEmulateXAdd
+%ifdef RT_ARCH_AMD64
+%ifdef RT_OS_WINDOWS
+    mov     rax, r8                     ; eax = size of parameters
+%else   ; !RT_OS_WINDOWS
+    mov     rax, rdx                    ; rax = size of parameters
+    mov     rcx, rdi                    ; rcx = first parameter
+    mov     rdx, rsi                    ; rdx = second parameter
+%endif  ; !RT_OS_WINDOWS
+%else   ; !RT_ARCH_AMD64
+    mov     eax, [esp + 0ch]            ; eax = size of parameters
+    mov     ecx, [esp + 04h]            ; ecx = first parameter
+    mov     edx, [esp + 08h]            ; edx = second parameter
+%endif
+
+    ; switch on size
+%ifdef CAN_DO_8_BYTE_OP
+    cmp     al, 8
+    je short .do_qword                  ; 8 bytes variant
+%endif
+    cmp     al, 4
+    je short .do_dword                  ; 4 bytes variant
+    cmp     al, 2
+    je short .do_word                   ; 2 byte variant
+    cmp     al, 1
+    je short .do_byte                   ; 1 bytes variant
+    int3
+
+    ; workers
+%ifdef RT_ARCH_AMD64
+.do_qword:
+    mov     rax, qword [xDX]            ; load 2nd parameter's value
+    xadd    qword [MY_PTR_REG], rax   ; do 8 bytes XADD
+    mov     qword [xDX], rax
+    jmp     short .done
+%endif
+
+.do_dword:
+    mov     eax, dword [xDX]            ; load 2nd parameter's value
+    xadd    dword [MY_PTR_REG], eax     ; do 4 bytes XADD
+    mov     dword [xDX], eax
+    jmp     short .done
+
+.do_word:
+    mov     eax, dword [xDX]            ; load 2nd parameter's value
+    xadd    word [MY_PTR_REG], ax       ; do 2 bytes XADD
+    mov     word [xDX], ax
+    jmp     short .done
+
+.do_byte:
+    mov     eax, dword [xDX]            ; load 2nd parameter's value
+    xadd    byte [MY_PTR_REG], al       ; do 1 bytes XADD
+    mov     byte [xDX], al
+
+.done:
+    ; collect flags and return.
+    pushf
+    pop     MY_RET_REG
+
+    retn
+
+%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
+.do_qword:
+    db      0xea                        ; jmp far .sixtyfourbit_mode
+    dd      .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
+BITS 64
+.sixtyfourbit_mode:
+    and     esp, 0ffffffffh
+    and     edx, 0ffffffffh
+    and     MY_PTR_REG, 0ffffffffh
+    mov     rax, qword [rdx]            ; load 2nd parameter's value
+    and     [MY_PTR_REG64], rax         ; do 8 bytes XADD
+    jmp far [.fpret wrt rip]
+.fpret:                                 ; 16:32 Pointer to .done.
+    dd      .done, NAME(SUPR0AbsKernelCS)
+BITS 32
+%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
+ENDPROC     EMEmulateXAdd
+
Index: trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp	(revision 30332)
+++ trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp	(revision 30338)
@@ -287,14 +287,8 @@
      *        raw mode code. Some thought needs to be spent on theoretical concurrency issues as
      *        as well since we're not behind the pgm lock and handler may change between calls.
-     *        MMGCRamWriteNoTrapHandler may also trap if the page isn't shadowed, or was kicked
-     *        out from both the shadow pt (SMP or our changes) and TLB.
      *
-     *        Currently MMGCRamWriteNoTrapHandler may also fail when it hits a write access handler.
-     *        PGMPhysInterpretedWriteNoHandlers/PGMPhysWriteGCPtr OTOH may mess up the state
-     *        of some shadowed structure in R0. */
-#ifdef IN_RC
-    NOREF(pCtxCore);
-    return MMGCRamWriteNoTrapHandler((void *)(uintptr_t)GCPtrDst, pvSrc, cb);
-#elif IN_RING0
+     *        PGMPhysInterpretedWriteNoHandlers/PGMPhysWriteGCPtr may mess up
+     *        the state of some shadowed structures. */
+#if defined(IN_RING0) || defined(IN_RC)
     return PGMPhysInterpretedWriteNoHandlers(pVCpu, pCtxCore, GCPtrDst, pvSrc, cb, false /*fRaiseTrap*/);
 #else
Index: trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp	(revision 30332)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp	(revision 30338)
@@ -3451,4 +3451,7 @@
      * 4. Set access bits if required.
      */
+    /** @todo Since this method is frequently used by EMInterpret or IOM
+     *        upon a write fault to an write access monitored page, we can
+     *        reuse the guest page table walking from the \#PF code. */
     int rc;
     unsigned cb1 = PAGE_SIZE - (GCPtrDst & PAGE_OFFSET_MASK);
