Index: /trunk/include/VBox/vmm/iom.h
===================================================================
--- /trunk/include/VBox/vmm/iom.h	(revision 45300)
+++ /trunk/include/VBox/vmm/iom.h	(revision 45301)
@@ -288,5 +288,5 @@
 VMMDECL(int)            IOMMMIOMapMMIOHCPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint64_t fPageFlags);
 VMMDECL(int)            IOMMMIOResetRegion(PVM pVM, RTGCPHYS GCPhys);
-VMMDECL(bool)           IOMIsLockOwner(PVM pVM);
+VMMDECL(bool)           IOMIsLockWriteOwner(PVM pVM);
 
 #ifdef IN_RC
Index: /trunk/include/VBox/vmm/vm.h
===================================================================
--- /trunk/include/VBox/vmm/vm.h	(revision 45300)
+++ /trunk/include/VBox/vmm/vm.h	(revision 45301)
@@ -990,5 +990,5 @@
         struct IOM s;
 #endif
-        uint8_t     padding[832];       /* multiple of 64 */
+        uint8_t     padding[896];       /* multiple of 64 */
     } iom;
 
@@ -1087,5 +1087,5 @@
 
     /** Padding for aligning the cpu array on a page boundary. */
-    uint8_t         abAlignment2[542];
+    uint8_t         abAlignment2[478];
 
     /* ---- end small stuff ---- */
Index: /trunk/src/VBox/VMM/VMMAll/EMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 45300)
+++ /trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 45301)
@@ -251,5 +251,5 @@
 
     Assert(!PGMIsLockOwner(pVM));
-    Assert(!IOMIsLockOwner(pVM));
+    Assert(!IOMIsLockWriteOwner(pVM));
     int rc = PDMCritSectEnter(&pVM->em.s.CritSectREM, VERR_SEM_BUSY);
     AssertRCSuccess(rc);
Index: /trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IOMAll.cpp	(revision 45300)
+++ /trunk/src/VBox/VMM/VMMAll/IOMAll.cpp	(revision 45301)
@@ -41,12 +41,16 @@
 
 /**
- * Check if this VCPU currently owns the IOM lock.
+ * Check if this VCPU currently owns the IOM lock exclusively.
  *
  * @returns bool owner/not owner
  * @param   pVM         Pointer to the VM.
  */
-VMMDECL(bool) IOMIsLockOwner(PVM pVM)
+VMMDECL(bool) IOMIsLockWriteOwner(PVM pVM)
 {
+#ifdef IOM_WITH_CRIT_SECT_RW
+    return PDMCritSectRwIsWriteOwner(&pVM->iom.s.CritSect);
+#else
     return PDMCritSectIsOwner(&pVM->iom.s.CritSect);
+#endif
 }
 
Index: /trunk/src/VBox/VMM/VMMR3/EM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/EM.cpp	(revision 45300)
+++ /trunk/src/VBox/VMM/VMMR3/EM.cpp	(revision 45301)
@@ -1694,5 +1694,5 @@
             if (    pVM->cCpus == 1
                 ||  (   !PGMIsLockOwner(pVM)
-                     && !IOMIsLockOwner(pVM))
+                     && !IOMIsLockWriteOwner(pVM))
                )
             {
Index: /trunk/src/VBox/VMM/VMMR3/IOM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/IOM.cpp	(revision 45300)
+++ /trunk/src/VBox/VMM/VMMR3/IOM.cpp	(revision 45301)
@@ -166,5 +166,9 @@
      * Initialize the REM critical section.
      */
+#ifdef IOM_WITH_CRIT_SECT_RW
+    int rc = PDMR3CritSectRwInit(pVM, &pVM->iom.s.CritSect, RT_SRC_POS, "IOM Lock");
+#else
     int rc = PDMR3CritSectInit(pVM, &pVM->iom.s.CritSect, RT_SRC_POS, "IOM Lock");
+#endif
     AssertRCReturn(rc, rc);
 
@@ -406,5 +410,6 @@
 PIOMIOPORTSTATS iomR3IOPortStatsCreate(PVM pVM, RTIOPORT Port, const char *pszDesc)
 {
-    Assert(IOMIsLockOwner(pVM));
+    Assert(IOM_IS_EXCL_LOCK_OWNER(pVM));
+
     /* check if it already exists. */
     PIOMIOPORTSTATS pPort = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.pTreesR3->IOPortStatTree, Port);
@@ -459,8 +464,9 @@
 PIOMMMIOSTATS iomR3MMIOStatsCreate(PVM pVM, RTGCPHYS GCPhys, const char *pszDesc)
 {
-    Assert(IOMIsLockOwner(pVM));
+    Assert(IOM_IS_EXCL_LOCK_OWNER(pVM));
 #ifdef DEBUG_sandervl
     AssertGCPhys32(GCPhys);
 #endif
+
     /* check if it already exists. */
     PIOMMMIOSTATS pStats = (PIOMMMIOSTATS)RTAvloGCPhysGet(&pVM->iom.s.pTreesR3->MmioStatTree, GCPhys);
Index: /trunk/src/VBox/VMM/include/IOMInline.h
===================================================================
--- /trunk/src/VBox/VMM/include/IOMInline.h	(revision 45300)
+++ /trunk/src/VBox/VMM/include/IOMInline.h	(revision 45301)
@@ -35,5 +35,5 @@
 DECLINLINE(CTX_SUFF(PIOMIOPORTRANGE)) iomIOPortGetRange(PVM pVM, RTIOPORT Port)
 {
-    Assert(PDMCritSectIsOwner(&pVM->iom.s.CritSect));
+    Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
     return (CTX_SUFF(PIOMIOPORTRANGE))RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->CTX_SUFF(IOPortTree), Port);
 }
@@ -51,5 +51,5 @@
 DECLINLINE(PIOMIOPORTRANGER3) iomIOPortGetRangeR3(PVM pVM, RTIOPORT Port)
 {
-    Assert(PDMCritSectIsOwner(&pVM->iom.s.CritSect));
+    Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
     return (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeR3, Port);
 }
@@ -67,5 +67,5 @@
 DECLINLINE(PIOMMMIORANGE) iomMmioGetRange(PVM pVM, RTGCPHYS GCPhys)
 {
-    Assert(PDMCritSectIsOwner(&pVM->iom.s.CritSect));
+    Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
     PIOMMMIORANGE pRange = pVM->iom.s.CTX_SUFF(pMMIORangeLast);
     if (    !pRange
@@ -102,5 +102,5 @@
 DECLINLINE(PIOMMMIORANGE) iomMmioGetRangeWithRef(PVM pVM, RTGCPHYS GCPhys)
 {
-    int rc = PDMCritSectEnter(&pVM->iom.s.CritSect, VINF_SUCCESS);
+    int rc = IOM_LOCK_SHARED_EX(pVM, VINF_SUCCESS);
     AssertRCReturn(rc, NULL);
 
@@ -113,5 +113,5 @@
         iomMmioRetainRange(pRange);
 
-    PDMCritSectLeave(&pVM->iom.s.CritSect);
+    IOM_UNLOCK_SHARED(pVM);
     return pRange;
 }
@@ -170,5 +170,5 @@
 DECLINLINE(PIOMMMIOSTATS) iomMmioGetStats(PVM pVM, RTGCPHYS GCPhys, PIOMMMIORANGE pRange)
 {
-    PDMCritSectEnter(&pVM->iom.s.CritSect, VINF_SUCCESS);
+    IOM_LOCK_SHARED_EX(pVM, VINF_SUCCESS);
 
     /* For large ranges, we'll put everything on the first byte. */
@@ -187,5 +187,5 @@
     }
 
-    PDMCritSectLeave(&pVM->iom.s.CritSect);
+    IOM_UNLOCK_SHARED(pVM);
     return pStats;
 }
Index: /trunk/src/VBox/VMM/include/IOMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IOMInternal.h	(revision 45300)
+++ /trunk/src/VBox/VMM/include/IOMInternal.h	(revision 45301)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -19,4 +19,6 @@
 #define ___IOMInternal_h
 
+//#define IOM_WITH_CRIT_SECT_RW
+
 #include <VBox/cdefs.h>
 #include <VBox/types.h>
@@ -25,4 +27,7 @@
 #include <VBox/vmm/pgm.h>
 #include <VBox/vmm/pdmcritsect.h>
+#ifdef IOM_WITH_CRIT_SECT_RW
+# include <VBox/vmm/pdmcritsectrw.h>
+#endif
 #include <VBox/param.h>
 #include <iprt/assert.h>
@@ -324,5 +329,9 @@
 
     /** Lock serializing EMT access to IOM. */
+#ifdef IOM_WITH_CRIT_SECT_RW
+    PDMCRITSECTRW                   CritSect;
+#else
     PDMCRITSECT                     CritSect;
+#endif
 
     /** @name Caching of I/O Port and MMIO ranges and statistics.
@@ -426,6 +435,26 @@
 
 /* IOM locking helpers. */
-#define IOM_LOCK(a_pVM)     PDMCritSectEnter(&(a_pVM)->iom.s.CritSect, VERR_SEM_BUSY)
-#define IOM_UNLOCK(a_pVM)   do { PDMCritSectLeave(&(a_pVM)->iom.s.CritSect); } while (0)
+#ifdef IOM_WITH_CRIT_SECT_RW
+# define IOM_LOCK(a_pVM)                        PDMCritSectRwEnterExcl(&(a_pVM)->iom.s.CritSect, VERR_SEM_BUSY)
+# define IOM_UNLOCK(a_pVM)                      do { PDMCritSectRwLeaveExcl(&(a_pVM)->iom.s.CritSect); } while (0)
+# if 1 /* for the time being (the lookup caches needs to be in VMCPU) */
+# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy)    PDMCritSectRwEnterExcl(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
+# define IOM_UNLOCK_SHARED(a_pVM)               do { PDMCritSectRwLeaveExcl(&(a_pVM)->iom.s.CritSect); } while (0)
+# define IOM_IS_SHARED_LOCK_OWNER(a_pVM)        PDMCritSectRwIsWriteOwner(&(a_pVM)->iom.s.CritSect)
+# else
+# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy)    PDMCritSectRwEnterShared(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
+# define IOM_UNLOCK_SHARED(a_pVM)               do { PDMCritSectRwLeaveShared(&(a_pVM)->iom.s.CritSect); } while (0)
+# define IOM_IS_SHARED_LOCK_OWNER(a_pVM)        PDMCritSectRwIsReadOwner(&(a_pVM)->iom.s.CritSect, true)
+# endif
+# define IOM_IS_EXCL_LOCK_OWNER(a_pVM)          PDMCritSectRwIsWriteOwner(&(a_pVM)->iom.s.CritSect)
+#else
+# define IOM_LOCK(a_pVM)                        PDMCritSectEnter(&(a_pVM)->iom.s.CritSect, VERR_SEM_BUSY)
+# define IOM_UNLOCK(a_pVM)                      do { PDMCritSectLeave(&(a_pVM)->iom.s.CritSect); } while (0)
+# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy)    PDMCritSectEnter(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
+# define IOM_UNLOCK_SHARED(a_pVM)               do { PDMCritSectLeave(&(a_pVM)->iom.s.CritSect); } while (0)
+# define IOM_IS_SHARED_LOCK_OWNER(a_pVM)        PDMCritSectIsOwner(&(a_pVM)->iom.s.CritSect)
+# define IOM_IS_EXCL_LOCK_OWNER(a_pVM)          PDMCritSectIsOwner(&(a_pVM)->iom.s.CritSect)
+#endif
+#define IOM_LOCK_SHARED(a_pVM)                  IOM_LOCK_SHARED_EX(a_pVM, VERR_SEM_BUSY)
 
 
