Index: trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IOMAll.cpp	(revision 19472)
+++ trunk/src/VBox/VMM/VMMAll/IOMAll.cpp	(revision 19474)
@@ -50,5 +50,5 @@
 int iomLock(PVM pVM)
 {
-    Assert(!PGMIsLocked(pVM));
+    Assert(!PGMIsLockOwner(pVM));
     int rc = PDMCritSectEnter(&pVM->iom.s.EmtLock, VERR_SEM_BUSY);
     return rc;
Index: trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp	(revision 19472)
+++ trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp	(revision 19474)
@@ -1049,4 +1049,12 @@
 VMMDECL(int) IOMMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)
 {
+    /* Take the IOM lock before performing any MMIO. */
+    int rc = iomLock(pVM);
+#ifndef IN_RING3
+    if (rc == VERR_SEM_BUSY)
+        return (uErrorCode & X86_TRAP_PF_RW) ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ;
+#endif
+    AssertRC(rc);
+
     STAM_PROFILE_START(&pVM->iom.s.StatRZMMIOHandler, a);
     Log(("IOMMMIOHandler: GCPhys=%RGp uErr=%#x pvFault=%RGv rip=%RGv\n",
@@ -1065,9 +1073,11 @@
     {
 # ifdef IN_RING3
+        iomUnlock(pVM);
         return VERR_NO_MEMORY;
 # else
         STAM_PROFILE_STOP(&pVM->iom.s.StatRZMMIOHandler, a);
         STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOFailures);
-        return uErrorCode & X86_TRAP_PF_RW ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ;
+        iomUnlock(pVM);
+        return (uErrorCode & X86_TRAP_PF_RW) ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ;
 # endif
     }
@@ -1091,5 +1101,6 @@
         STAM_PROFILE_STOP(&pVM->iom.s.StatRZMMIOHandler, a);
         STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOFailures);
-        return uErrorCode & X86_TRAP_PF_RW ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ;
+        iomUnlock(pVM);
+        return (uErrorCode & X86_TRAP_PF_RW ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ);
     }
 #endif /* !IN_RING3 */
@@ -1100,6 +1111,11 @@
     DISCPUSTATE Cpu;
     unsigned cbOp;
-    int rc = EMInterpretDisasOne(pVM, VMMGetCpu(pVM), pCtxCore, &Cpu, &cbOp);
-    AssertRCReturn(rc, rc);
+    rc = EMInterpretDisasOne(pVM, VMMGetCpu(pVM), pCtxCore, &Cpu, &cbOp);
+    AssertRC(rc);
+    if (RT_FAILURE(rc))
+    {
+        iomUnlock(pVM);
+        return rc;
+    }
     switch (Cpu.pCurInstr->opcode)
     {
@@ -1224,4 +1240,5 @@
 
     STAM_PROFILE_STOP(&pVM->iom.s.StatRZMMIOHandler, a);
+    iomUnlock(pVM);
     return rc;
 }
@@ -1244,7 +1261,10 @@
 DECLCALLBACK(int) IOMR3MMIOHandler(PVM pVM, RTGCPHYS GCPhysFault, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
 {
-    int           rc;
     PIOMMMIORANGE pRange = (PIOMMMIORANGE)pvUser;
     STAM_COUNTER_INC(&pVM->iom.s.StatR3MMIOHandler);
+
+    /* Take the IOM lock before performing any MMIO. */
+    int rc = iomLock(pVM);
+    AssertRC(rc);
 
     AssertMsg(cbBuf == 1 || cbBuf == 2 || cbBuf == 4 || cbBuf == 8, ("%zu\n", cbBuf));
@@ -1259,8 +1279,8 @@
 
     AssertRC(rc);
+    iomUnlock(pVM);
     return rc;
 }
 #endif /* IN_RING3 */
-
 
 /**
@@ -1276,14 +1296,27 @@
 VMMDECL(int) IOMMMIORead(PVM pVM, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue)
 {
+    /* Take the IOM lock before performing any MMIO. */
+    int rc = iomLock(pVM);
+#ifndef IN_RING3
+    if (rc == VERR_SEM_BUSY)
+        return VINF_IOM_HC_MMIO_WRITE;
+#endif
+    AssertRC(rc);
+
     /*
      * Lookup the current context range node and statistics.
      */
     PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys);
-    AssertMsgReturn(pRange,
-                    ("Handlers and page tables are out of sync or something! GCPhys=%RGp cbValue=%d\n", GCPhys, cbValue),
-                    VERR_INTERNAL_ERROR);
+    AssertMsg(pRange, ("Handlers and page tables are out of sync or something! GCPhys=%RGp cbValue=%d\n", GCPhys, cbValue));
+    if (!pRange)
+    {
+        iomUnlock(pVM);
+        return VERR_INTERNAL_ERROR;
+    }
 #ifdef VBOX_WITH_STATISTICS
     PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhys, pRange);
     if (!pStats)
+    {
+        iomUnlock(pVM);
 # ifdef IN_RING3
         return VERR_NO_MEMORY;
@@ -1291,4 +1324,5 @@
         return VINF_IOM_HC_MMIO_READ;
 # endif
+    }
 #endif /* VBOX_WITH_STATISTICS */
     if (pRange->CTX_SUFF(pfnReadCallback))
@@ -1300,5 +1334,5 @@
         STAM_PROFILE_ADV_START(&pStats->CTX_SUFF_Z(ProfRead), a);
 #endif
-        int rc = pRange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhys, pu32Value, (unsigned)cbValue);
+        rc = pRange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhys, pu32Value, (unsigned)cbValue);
 #ifdef VBOX_WITH_STATISTICS
         STAM_PROFILE_ADV_STOP(&pStats->CTX_SUFF_Z(ProfRead), a);
@@ -1311,4 +1345,5 @@
             default:
                 Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=%Rrc\n", GCPhys, *pu32Value, cbValue, rc));
+                iomUnlock(pVM);
                 return rc;
 
@@ -1323,4 +1358,5 @@
                 }
                 Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=%Rrc\n", GCPhys, *pu32Value, cbValue, rc));
+                iomUnlock(pVM);
                 return VINF_SUCCESS;
 
@@ -1335,4 +1371,5 @@
                 }
                 Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=%Rrc\n", GCPhys, *pu32Value, cbValue, rc));
+                iomUnlock(pVM);
                 return VINF_SUCCESS;
         }
@@ -1342,4 +1379,5 @@
     {
         STAM_COUNTER_INC(&pStats->CTX_MID_Z(Read,ToR3));
+        iomUnlock(pVM);
         return VINF_IOM_HC_MMIO_READ;
     }
@@ -1362,4 +1400,5 @@
     }
     Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=VINF_SUCCESS\n", GCPhys, *pu32Value, cbValue));
+    iomUnlock(pVM);
     return VINF_SUCCESS;
 }
@@ -1378,14 +1417,27 @@
 VMMDECL(int) IOMMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue)
 {
+    /* Take the IOM lock before performing any MMIO. */
+    int rc = iomLock(pVM);
+#ifndef IN_RING3
+    if (rc == VERR_SEM_BUSY)
+        return VINF_IOM_HC_MMIO_WRITE;
+#endif
+    AssertRC(rc);
+
     /*
      * Lookup the current context range node.
      */
     PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys);
-    AssertMsgReturn(pRange,
-                    ("Handlers and page tables are out of sync or something! GCPhys=%RGp cbValue=%d\n", GCPhys, cbValue),
-                    VERR_INTERNAL_ERROR);
+    AssertMsg(pRange, ("Handlers and page tables are out of sync or something! GCPhys=%RGp cbValue=%d\n", GCPhys, cbValue));
+    if (!pRange)
+    {
+        iomUnlock(pVM);
+        return VERR_INTERNAL_ERROR;
+    }
 #ifdef VBOX_WITH_STATISTICS
     PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhys, pRange);
     if (!pStats)
+    {
+        iomUnlock(pVM);
 # ifdef IN_RING3
         return VERR_NO_MEMORY;
@@ -1393,4 +1445,5 @@
         return VINF_IOM_HC_MMIO_WRITE;
 # endif
+    }
 #endif /* VBOX_WITH_STATISTICS */
 
@@ -1404,5 +1457,5 @@
         STAM_PROFILE_ADV_START(&pStats->CTX_SUFF_Z(ProfWrite), a);
 #endif
-        int rc = pRange->CTX_SUFF(pfnWriteCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhys, &u32Value, (unsigned)cbValue);
+        rc = pRange->CTX_SUFF(pfnWriteCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhys, &u32Value, (unsigned)cbValue);
 #ifdef VBOX_WITH_STATISTICS
         STAM_PROFILE_ADV_STOP(&pStats->CTX_SUFF_Z(ProfWrite), a);
@@ -1411,4 +1464,5 @@
 #endif
         Log4(("IOMMMIOWrite: GCPhys=%RGp u32=%08RX32 cb=%d rc=%Rrc\n", GCPhys, u32Value, cbValue, rc));
+        iomUnlock(pVM);
         return rc;
     }
@@ -1417,4 +1471,5 @@
     {
         STAM_COUNTER_INC(&pStats->CTX_MID_Z(Write,ToR3));
+        iomUnlock(pVM);
         return VINF_IOM_HC_MMIO_WRITE;
     }
@@ -1428,7 +1483,7 @@
 #endif
     Log4(("IOMMMIOWrite: GCPhys=%RGp u32=%08RX32 cb=%d rc=%Rrc\n", GCPhys, u32Value, cbValue, VINF_SUCCESS));
+    iomUnlock(pVM);
     return VINF_SUCCESS;
 }
-
 
 /**
Index: trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 19472)
+++ trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 19474)
@@ -2030,4 +2030,17 @@
 }
 
+
+/**
+ * Check if this VCPU currently owns the PGM lock.
+ *
+ * @returns bool owner/not owner
+ * @param   pVM         The VM to operate on.
+ */
+VMMDECL(bool) PGMIsLockOwner(PVM pVM)
+{
+    return PDMCritSectIsOwner(&pVM->pgm.s.CritSect);
+}
+
+
 /**
  * Acquire the PGM lock.
