Index: trunk/include/VBox/VMMDev.h
===================================================================
--- trunk/include/VBox/VMMDev.h	(revision 100184)
+++ trunk/include/VBox/VMMDev.h	(revision 100185)
@@ -54,4 +54,13 @@
  */
 
+/** The VMMDev assumed page size (not the real guest page size which might be different
+ * between guest and host, on ARM for example), 4KiB is the minimum supported by both
+ * ARM and x86 and was the one used back when the device supported x86 only. */
+#define VMMDEV_PAGE_SIZE                                    _4K
+/** The VMMDev assumed page shift. */
+#define VMMDEV_PAGE_SHIFT                                   12
+/** The VMMDev assumed page offset mask. */
+#define VMMDEV_PAGE_OFFSET_MASK                             0xfff
+
 
 /** Size of VMMDev RAM region accessible by guest.
@@ -59,10 +68,10 @@
  * For now: 4 megabyte.
  */
-#define VMMDEV_RAM_SIZE                                     (4 * 256 * PAGE_SIZE)
+#define VMMDEV_RAM_SIZE                                     (4 * 256 * VMMDEV_PAGE_SIZE)
 
 /** Size of VMMDev heap region accessible by guest.
  *  (Must be a power of two (pci range).)
  */
-#define VMMDEV_HEAP_SIZE                                    (4 * PAGE_SIZE)
+#define VMMDEV_HEAP_SIZE                                    (4 * VMMDEV_PAGE_SIZE)
 
 /** Port for generic request interface (relative offset). */
@@ -71,4 +80,13 @@
  * This works like VMMDevReq_AcknowledgeEvents when read.  */
 #define VMMDEV_PORT_OFF_REQUEST_FAST                        8
+
+
+/** The MMIO region size if MMIO is used instead of PIO. */
+#define VMMDEV_MMIO_SIZE                                    _4K
+/** Port for generic request interface (relative offset). */
+#define VMMDEV_MMIO_OFF_REQUEST                             0
+/** Port for requests that can be handled w/o going to ring-3 (relative offset).
+ * This works like VMMDevReq_AcknowledgeEvents when read.  */
+#define VMMDEV_MMIO_OFF_REQUEST_FAST                        8
 
 
Index: trunk/src/VBox/Devices/VMMDev/VMMDev.cpp
===================================================================
--- trunk/src/VBox/Devices/VMMDev/VMMDev.cpp	(revision 100184)
+++ trunk/src/VBox/Devices/VMMDev/VMMDev.cpp	(revision 100185)
@@ -1832,5 +1832,5 @@
     {
         /*
-         * Note! This code is duplicated in vmmdevFastRequestIrqAck.
+         * Note! This code is duplicated in vmmdevPioFastRequestIrqAck.
          */
         if (pThis->fNewGuestFilterMaskValid)
@@ -3076,14 +3076,14 @@
 
 /**
- * @callback_method_impl{FNIOMIOPORTNEWOUT,
- * Port I/O write andler for the generic request interface.}
- */
-static DECLCALLBACK(VBOXSTRICTRC)
-vmmdevRequestHandler(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
+ * The request handler shared by the PIO and MMIO access paths.
+ *
+ * @returns Strict VBox status code.
+ * @param   pDevIns         The device instance.
+ * @param   GCPhysReqHdr    Physical address of the request header.
+ */
+static VBOXSTRICTRC vmmdevRequestHandler(PPDMDEVINS pDevIns, RTGCPHYS GCPhysReqHdr)
 {
     uint64_t tsArrival;
     STAM_GET_TS(tsArrival);
-
-    RT_NOREF(offPort, cb, pvUser);
 
     /*
@@ -3094,5 +3094,5 @@
     VMMDevRequestHeader requestHeader;
     RT_ZERO(requestHeader);
-    PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)u32, &requestHeader, sizeof(requestHeader));
+    PDMDevHlpPhysRead(pDevIns, GCPhysReqHdr, &requestHeader, sizeof(requestHeader));
 
     /* The structure size must be greater or equal to the header size. */
@@ -3171,6 +3171,6 @@
                     if (   (   requestHeader.requestType == VMMDevReq_HGCMCall32
                             || requestHeader.requestType == VMMDevReq_HGCMCall64)
-                        && ((u32 + requestHeader.size) >> X86_PAGE_SHIFT) == (u32 >> X86_PAGE_SHIFT)
-                        && RT_SUCCESS(PDMDevHlpPhysGCPhys2CCPtr(pDevIns, u32, 0 /*fFlags*/, &Lock.pvReq, &Lock.Lock)) )
+                        && ((GCPhysReqHdr + requestHeader.size) >> VMMDEV_PAGE_SHIFT) == (GCPhysReqHdr >> VMMDEV_PAGE_SHIFT)
+                        && RT_SUCCESS(PDMDevHlpPhysGCPhys2CCPtr(pDevIns, GCPhysReqHdr, 0 /*fFlags*/, &Lock.pvReq, &Lock.Lock)) )
                     {
                         memcpy((uint8_t *)pRequestHeader + sizeof(VMMDevRequestHeader),
@@ -3180,5 +3180,5 @@
                     else
                         PDMDevHlpPhysRead(pDevIns,
-                                          (RTGCPHYS)u32             + sizeof(VMMDevRequestHeader),
+                                          GCPhysReqHdr              + sizeof(VMMDevRequestHeader),
                                           (uint8_t *)pRequestHeader + sizeof(VMMDevRequestHeader),
                                           cbLeft);
@@ -3192,5 +3192,5 @@
                 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock);
 
-                rcRet = vmmdevReqDispatcher(pDevIns, pThis, pThisCC, pRequestHeader, u32, tsArrival, &fPostOptimize, &pLock);
+                rcRet = vmmdevReqDispatcher(pDevIns, pThis, pThisCC, pRequestHeader, GCPhysReqHdr, tsArrival, &fPostOptimize, &pLock);
 
                 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
@@ -3204,5 +3204,5 @@
                         memcpy(pLock->pvReq, pRequestHeader, pRequestHeader->size);
                     else
-                        PDMDevHlpPhysWrite(pDevIns, u32, pRequestHeader, pRequestHeader->size);
+                        PDMDevHlpPhysWrite(pDevIns, GCPhysReqHdr, pRequestHeader, pRequestHeader->size);
                 }
 
@@ -3233,10 +3233,95 @@
      * Write the result back to guest memory.
      */
-    PDMDevHlpPhysWrite(pDevIns, u32, &requestHeader, sizeof(requestHeader));
+    PDMDevHlpPhysWrite(pDevIns, GCPhysReqHdr, &requestHeader, sizeof(requestHeader));
 
     return rcRet;
 }
 
+
+/**
+ * @callback_method_impl{FNIOMIOPORTNEWOUT,
+ * Port I/O write andler for the generic request interface.}
+ */
+static DECLCALLBACK(VBOXSTRICTRC)
+vmmdevPioRequestHandler(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
+{
+    RT_NOREF(offPort, cb, pvUser);
+
+    return vmmdevRequestHandler(pDevIns, u32);
+}
+
 #endif /* IN_RING3 */
+
+
+/**
+ * Common worker for hanlding the fast interrupt acknowledge path from both
+ * PIO and MMIO access handlers.
+ *
+ * @returns Strict VBox status code.
+ * @param   pDevIns         The device instance.
+ * @param   pu32            Where to store the host event flags.
+ * @param   rcToR3          The status code to return when locking failed in
+ *                          non ring-3/userspace environments (R0 or RC).
+ */
+static VBOXSTRICTRC vmmdevFastReqIrqAck(PPDMDEVINS pDevIns, uint32_t *pu32, int rcToR3)
+{
+    PVMMDEV   pThis   = PDMDEVINS_2_DATA(pDevIns, PVMMDEV);
+    PVMMDEVCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVMMDEVCC);
+    Assert(PDMDEVINS_2_DATA(pDevIns, PVMMDEV) == pThis);
+
+#ifdef IN_RING3
+    RT_NOREF(rcToR3);
+#endif
+
+    /* The VMMDev memory mapping might've failed, go to ring-3 in that case. */
+    VBOXSTRICTRC rcStrict;
+#ifndef IN_RING3
+    if (pThisCC->CTX_SUFF(pVMMDevRAM) != NULL)
+#endif
+    {
+        /* Enter critical section and check that the additions has been properly
+           initialized and that we're not in legacy v1.3 device mode. */
+        rcStrict = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, rcToR3);
+        if (rcStrict == VINF_SUCCESS)
+        {
+            if (   pThis->fu32AdditionsOk
+                && !VMMDEV_INTERFACE_VERSION_IS_1_03(pThis))
+            {
+                /*
+                 * Do the job.
+                 *
+                 * Note! This code is duplicated in vmmdevReqHandler_AcknowledgeEvents.
+                 */
+                STAM_REL_COUNTER_INC(&pThis->CTX_SUFF_Z(StatFastIrqAck));
+
+                if (pThis->fNewGuestFilterMaskValid)
+                {
+                    pThis->fNewGuestFilterMaskValid = false;
+                    pThis->fGuestFilterMask = pThis->fNewGuestFilterMask;
+                }
+
+                *pu32 = pThis->fHostEventFlags & pThis->fGuestFilterMask;
+
+                pThis->fHostEventFlags &= ~pThis->fGuestFilterMask;
+                pThisCC->CTX_SUFF(pVMMDevRAM)->V.V1_04.fHaveEvents = false;
+
+                PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
+            }
+            else
+            {
+                Log(("vmmdevFastRequestIrqAck: fu32AdditionsOk=%d interfaceVersion=%#x\n", pThis->fu32AdditionsOk,
+                     pThis->guestInfo.interfaceVersion));
+                *pu32 = UINT32_MAX;
+            }
+
+            PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
+        }
+    }
+#ifndef IN_RING3
+    else
+        rcStrict = rcToR3;
+#endif
+    return rcStrict;
+}
 
 
@@ -3246,8 +3331,8 @@
  */
 static DECLCALLBACK(VBOXSTRICTRC)
-vmmdevFastRequestHandler(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
+vmmdevPioFastRequestHandler(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
 {
 #ifndef IN_RING3
-# if 0 /* This functionality is offered through reading the port (vmmdevFastRequestIrqAck). Leaving it here for later. */
+# if 0 /* This functionality is offered through reading the port (vmmdevPioFastRequestIrqAck). Leaving it here for later. */
     PVMMDEV pThis = PDMDEVINS_2_DATA(pDevIns, PVMMDEV);
     RT_NOREF(pvUser, Port, cb);
@@ -3334,5 +3419,5 @@
 
 #else  /* IN_RING3 */
-    return vmmdevRequestHandler(pDevIns, pvUser, offPort, u32, cb);
+    return vmmdevPioRequestHandler(pDevIns, pvUser, offPort, u32, cb);
 #endif /* IN_RING3 */
 }
@@ -3345,9 +3430,6 @@
  */
 static DECLCALLBACK(VBOXSTRICTRC)
-vmmdevFastRequestIrqAck(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
-{
-    PVMMDEV   pThis   = PDMDEVINS_2_DATA(pDevIns, PVMMDEV);
-    PVMMDEVCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVMMDEVCC);
-    Assert(PDMDEVINS_2_DATA(pDevIns, PVMMDEV) == pThis);
+vmmdevPioFastRequestIrqAck(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
+{
     RT_NOREF(pvUser, offPort);
 
@@ -3355,52 +3437,78 @@
     ASSERT_GUEST_MSG_RETURN(cb == sizeof(uint32_t), ("cb=%d\n", cb), VERR_IOM_IOPORT_UNUSED);
 
-    /* The VMMDev memory mapping might've failed, go to ring-3 in that case. */
+    return vmmdevFastReqIrqAck(pDevIns, pu32, VINF_IOM_R3_IOPORT_READ);
+}
+
+
+/**
+ * @callback_method_impl{FNIOMMMIONEWREAD, Read a MMIO register.}
+ */
+static DECLCALLBACK(VBOXSTRICTRC) vmmdevMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb)
+{
+    const uint32_t offReg = (uint32_t)off;
+    RT_NOREF(pvUser);
+
+    /* Only 32-bit accesses. */
+    ASSERT_GUEST_MSG_RETURN(cb == sizeof(uint32_t), ("cb=%d\n", cb), VINF_IOM_MMIO_UNUSED_FF);
+
+    Log2(("vmmdevMmioRead %RGp (offset %04X) size=%u\n", off, offReg, cb));
+
     VBOXSTRICTRC rcStrict;
+    switch (offReg)
+    {
+        case VMMDEV_MMIO_OFF_REQUEST_FAST:
+            rcStrict = vmmdevFastReqIrqAck(pDevIns, (uint32_t *)pv, VINF_IOM_R3_MMIO_READ);
+            break;
+        case VMMDEV_MMIO_OFF_REQUEST:
+        default:
+            Log(("VMMDev: Trying to read unimplemented register at offset %04X!\n", offReg));
+            rcStrict = VINF_IOM_MMIO_UNUSED_FF;
+            break;
+    }
+
+    return rcStrict;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMMMIONEWWRITE, Write to a MMIO register.}
+ */
+static DECLCALLBACK(VBOXSTRICTRC) vmmdevMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
+{
+    const uint32_t offReg = (uint32_t)off;
+    RT_NOREF(pvUser);
+
+    /* Only 32-bit and 64-bit accesses. */
+    ASSERT_GUEST_MSG_RETURN(cb == sizeof(uint32_t) || cb == sizeof(uint64_t),
+                            ("cb=%u\n", cb), VINF_IOM_MMIO_UNUSED_FF);
+
+    uint64_t u64Val;
+    if (cb == sizeof(uint64_t))
+        u64Val = *(uint64_t *)pv;
+    else if (cb == sizeof(uint32_t))
+        u64Val = *(uint32_t *)pv;
+
+    Log2(("vmmdevMmioWrite %RGp (offset %04X) %#RX64 size=%u\n", off, offReg, u64Val, cb));
+
+    VBOXSTRICTRC rcStrict;
+    switch (offReg)
+    {
+        case VMMDEV_MMIO_OFF_REQUEST:
+            rcStrict = vmmdevRequestHandler(pDevIns, u64Val);
+            break;
+        case VMMDEV_MMIO_OFF_REQUEST_FAST:
 #ifndef IN_RING3
-    if (pThisCC->CTX_SUFF(pVMMDevRAM) != NULL)
+            rcStrict = VINF_IOM_R3_MMIO_WRITE;
+#else
+            rcStrict = vmmdevRequestHandler(pDevIns, u64Val);
 #endif
-    {
-        /* Enter critical section and check that the additions has been properly
-           initialized and that we're not in legacy v1.3 device mode. */
-        rcStrict = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_IOM_R3_IOPORT_READ);
-        if (rcStrict == VINF_SUCCESS)
-        {
-            if (   pThis->fu32AdditionsOk
-                && !VMMDEV_INTERFACE_VERSION_IS_1_03(pThis))
-            {
-                /*
-                 * Do the job.
-                 *
-                 * Note! This code is duplicated in vmmdevReqHandler_AcknowledgeEvents.
-                 */
-                STAM_REL_COUNTER_INC(&pThis->CTX_SUFF_Z(StatFastIrqAck));
-
-                if (pThis->fNewGuestFilterMaskValid)
-                {
-                    pThis->fNewGuestFilterMaskValid = false;
-                    pThis->fGuestFilterMask = pThis->fNewGuestFilterMask;
-                }
-
-                *pu32 = pThis->fHostEventFlags & pThis->fGuestFilterMask;
-
-                pThis->fHostEventFlags &= ~pThis->fGuestFilterMask;
-                pThisCC->CTX_SUFF(pVMMDevRAM)->V.V1_04.fHaveEvents = false;
-
-                PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
-            }
-            else
-            {
-                Log(("vmmdevFastRequestIrqAck: fu32AdditionsOk=%d interfaceVersion=%#x\n", pThis->fu32AdditionsOk,
-                     pThis->guestInfo.interfaceVersion));
-                *pu32 = UINT32_MAX;
-            }
-
-            PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
-        }
-    }
-#ifndef IN_RING3
-    else
-        rcStrict = VINF_IOM_R3_IOPORT_READ;
-#endif
+            break;
+        default:
+            /* Ignore writes to unimplemented or read-only registers. */
+            Log(("VMMDev: Trying to write unimplemented or R/O register at offset %04X!\n", offReg));
+            rcStrict = VINF_SUCCESS;
+            break;
+    }
+
     return rcStrict;
 }
@@ -4091,4 +4199,5 @@
     pHlp->pfnSSMPutBool(pSSM, pThis->fKeepCredentials);
     pHlp->pfnSSMPutBool(pSSM, pThis->fHeapEnabled);
+    pHlp->pfnSSMPutBool(pSSM, pThis->fMmioReq);
 
     return VINF_SSM_DONT_CALL_AGAIN;
@@ -4197,4 +4306,14 @@
             return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - fHeapEnabled: config=%RTbool saved=%RTbool"),
                                            pThis->fHeapEnabled, f);
+
+        f = false;
+        if (uVersion >= VMMDEV_SAVED_STATE_VERSION_MMIO_ACCESS)
+        {
+            rc = pHlp->pfnSSMGetBool(pSSM, &f);
+            AssertRCReturn(rc, rc);
+        }
+        if (pThis->fMmioReq != f)
+            return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - fMmioReq: config=%RTbool saved=%RTbool"),
+                                           pThis->fMmioReq, f);
     }
 
@@ -4726,4 +4845,5 @@
                                   "HeartbeatInterval|"
                                   "HeartbeatTimeout|"
+                                  "MmioReq|"
                                   "TestingEnabled|"
                                   "TestingMMIO|"
@@ -4771,5 +4891,7 @@
                                 N_("Configuration error: Failed querying \"KeepCredentials\" as a boolean"));
 
-    rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "HeapEnabled", &pThis->fHeapEnabled, true);
+    /* The heap is of no use on non x86 guest architectures. */
+    static const bool fHeapEnabledDef = PDMDevHlpCpuIsGuestArchX86(pDevIns);
+    rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "HeapEnabled", &pThis->fHeapEnabled, fHeapEnabledDef);
     if (RT_FAILURE(rc))
         return PDMDEV_SET_ERROR(pDevIns, rc,
@@ -4811,4 +4933,10 @@
                                    N_("Configuration error: Heartbeat timeout \"HeartbeatTimeout\" value (%'ull ns) is too close to the interval (%'ull ns)"),
                                    pThis->cNsHeartbeatTimeout, pThis->cNsHeartbeatInterval);
+
+    /* On everthing els than x86 we have to offer the MMIO interface because port I/O is either not available or emulated through MMIO anyway. */
+    static const bool fMmioReqEnabledDef = !PDMDevHlpCpuIsGuestArchX86(pDevIns);
+    rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "MmioReq", &pThis->fMmioReq, fMmioReqEnabledDef);
+    if (RT_FAILURE(rc))
+        return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed querying \"MmioReq\" as a boolean"));
 
 #ifndef VBOX_WITHOUT_TESTING_FEATURES
@@ -4938,10 +5066,10 @@
      * so we have to do it via the mapper callback.
      */
-    rc = PDMDevHlpIoPortCreate(pDevIns, 1 /*cPorts*/, pPciDev, RT_MAKE_U32(0, 0), vmmdevRequestHandler, NULL /*pfnIn*/,
+    rc = PDMDevHlpIoPortCreate(pDevIns, 1 /*cPorts*/, pPciDev, RT_MAKE_U32(0, 0), vmmdevPioRequestHandler, NULL /*pfnIn*/,
                                NULL /*pvUser*/, "VMMDev Request Handler",  NULL, &pThis->hIoPortReq);
     AssertRCReturn(rc, rc);
 
-    rc = PDMDevHlpIoPortCreate(pDevIns, 1 /*cPorts*/, pPciDev, RT_MAKE_U32(1, 0),  vmmdevFastRequestHandler,
-                               vmmdevFastRequestIrqAck, NULL, "VMMDev Fast R0/RC Requests", NULL /*pvUser*/, &pThis->hIoPortFast);
+    rc = PDMDevHlpIoPortCreate(pDevIns, 1 /*cPorts*/, pPciDev, RT_MAKE_U32(1, 0),  vmmdevPioFastRequestHandler,
+                               vmmdevPioFastRequestIrqAck, NULL, "VMMDev Fast R0/RC Requests", NULL /*pvUser*/, &pThis->hIoPortFast);
     AssertRCReturn(rc, rc);
 
@@ -4976,4 +5104,13 @@
         rc = PDMDevHlpRegisterVMMDevHeap(pDevIns, NIL_RTGCPHYS, pThisCC->pVMMDevHeapR3, VMMDEV_HEAP_SIZE);
         AssertLogRelRCReturn(rc, rc);
+    }
+
+    if (pThis->fMmioReq)
+    {
+        rc = PDMDevHlpPCIIORegionCreateMmio(pDevIns, 3 /*iPciRegion*/, VMMDEV_MMIO_SIZE, PCI_ADDRESS_SPACE_MEM,
+                                            vmmdevMmioWrite, vmmdevMmioRead, NULL,
+                                            IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
+                                            "VMMDev MMIO Request Handler", &pThis->hMmioReq);
+        AssertRCReturn(rc, rc);
     }
 
@@ -5123,11 +5260,17 @@
     /*
      * We map the first page of the VMMDevRAM into raw-mode and kernel contexts so we
-     * can handle interrupt acknowledge requests more timely (vmmdevFastRequestIrqAck).
-     */
-    rc = PDMDevHlpMmio2SetUpContext(pDevIns, pThis->hMmio2VMMDevRAM, 0, GUEST_PAGE_SIZE, (void **)&pThisCC->CTX_SUFF(pVMMDevRAM));
+     * can handle interrupt acknowledge requests more timely (vmmdevPioFastRequestIrqAck).
+     */
+    rc = PDMDevHlpMmio2SetUpContext(pDevIns, pThis->hMmio2VMMDevRAM, 0, VMMDEV_PAGE_SIZE, (void **)&pThisCC->CTX_SUFF(pVMMDevRAM));
     AssertRCReturn(rc, rc);
 
-    rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->hIoPortFast, vmmdevFastRequestHandler, vmmdevFastRequestIrqAck, NULL);
+    rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->hIoPortFast, vmmdevPioFastRequestHandler, vmmdevPioFastRequestIrqAck, NULL);
     AssertRCReturn(rc, rc);
+
+    if (pThis->fMmioReq)
+    {
+        rc = PDMDevHlpMmioSetUpContext(pDevIns, pThis->hMmioReq, vmmdevMmioWrite, vmmdevMmioRead, NULL /*pvUser*/);
+        AssertRCReturn(rc, rc);
+    }
 
 # ifndef VBOX_WITHOUT_TESTING_FEATURES
Index: trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp
===================================================================
--- trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp	(revision 100184)
+++ trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp	(revision 100185)
@@ -691,5 +691,5 @@
     if (pPtr->cPages == 1)
         return true;
-    RTGCPHYS64 Phys = pPtr->paPages[0] + GUEST_PAGE_SIZE;
+    RTGCPHYS64 Phys = pPtr->paPages[0] + VMMDEV_PAGE_SIZE;
     if (Phys != pPtr->paPages[1])
         return false;
@@ -699,5 +699,5 @@
         do
         {
-            Phys += GUEST_PAGE_SIZE;
+            Phys += VMMDEV_PAGE_SIZE;
             if (Phys != pPtr->paPages[iPage])
                 return false;
@@ -734,5 +734,5 @@
     for (uint32_t iPage = 0; iPage < pPtr->cPages && cbRemaining > 0; ++iPage)
     {
-        uint32_t cbToRead = GUEST_PAGE_SIZE - offPage;
+        uint32_t cbToRead = VMMDEV_PAGE_SIZE - offPage;
         if (cbToRead > cbRemaining)
             cbToRead = cbRemaining;
@@ -773,5 +773,5 @@
     for (iPage = 0; iPage < pPtr->cPages && cbRemaining > 0; ++iPage)
     {
-        uint32_t cbToWrite = GUEST_PAGE_SIZE - offPage;
+        uint32_t cbToWrite = VMMDEV_PAGE_SIZE - offPage;
         if (cbToWrite > cbRemaining)
             cbToWrite = cbRemaining;
@@ -1098,6 +1098,6 @@
                 ASSERT_GUEST_RETURN(cbData <= VMMDEV_MAX_HGCM_DATA_SIZE, VERR_INVALID_PARAMETER);
 
-                const uint32_t offFirstPage = cbData > 0 ? GCPtr & GUEST_PAGE_OFFSET_MASK : 0;
-                const uint32_t cPages       = cbData > 0 ? (offFirstPage + cbData + GUEST_PAGE_SIZE - 1) / GUEST_PAGE_SIZE : 0;
+                const uint32_t offFirstPage = cbData > 0 ? GCPtr & VMMDEV_PAGE_OFFSET_MASK : 0;
+                const uint32_t cPages       = cbData > 0 ? (offFirstPage + cbData + VMMDEV_PAGE_SIZE - 1) / VMMDEV_PAGE_SIZE : 0;
 
                 pGuestParm->u.ptr.cbData        = cbData;
@@ -1119,5 +1119,5 @@
 
                     /* Gonvert the guest linear pointers of pages to physical addresses. */
-                    GCPtr &= ~(RTGCPTR)GUEST_PAGE_OFFSET_MASK;
+                    GCPtr &= ~(RTGCPTR)VMMDEV_PAGE_OFFSET_MASK;
                     for (uint32_t iPage = 0; iPage < cPages; ++iPage)
                     {
@@ -1134,5 +1134,5 @@
 
                         pGuestParm->u.ptr.paPages[iPage] = GCPhys;
-                        GCPtr += GUEST_PAGE_SIZE;
+                        GCPtr += VMMDEV_PAGE_SIZE;
                     }
                 }
@@ -1179,5 +1179,5 @@
                                         ("%#x\n", pPageListInfo->flags), VERR_INVALID_FLAGS);
                 /* First page offset. */
-                ASSERT_GUEST_MSG_RETURN(pPageListInfo->offFirstPage < GUEST_PAGE_SIZE,
+                ASSERT_GUEST_MSG_RETURN(pPageListInfo->offFirstPage < VMMDEV_PAGE_SIZE,
                                         ("%#x\n", pPageListInfo->offFirstPage), VERR_INVALID_PARAMETER);
 
@@ -1187,6 +1187,6 @@
                 ASSERT_GUEST_MSG_RETURN(      pPageListInfo->cPages
                                            == (pGuestParm->enmType == VMMDevHGCMParmType_ContiguousPageList ? 1
-                                               :    RT_ALIGN_32(pPageListInfo->offFirstPage + cbData, GUEST_PAGE_SIZE)
-                                                 >> GUEST_PAGE_SHIFT)
+                                               :    RT_ALIGN_32(pPageListInfo->offFirstPage + cbData, VMMDEV_PAGE_SIZE)
+                                                 >> VMMDEV_PAGE_SHIFT)
                                         || pGuestParm->enmType == VMMDevHGCMParmType_PageList,
                                         ("offFirstPage=%#x cbData=%#x cPages=%#x enmType=%d\n",
@@ -1203,11 +1203,11 @@
                 {
                     /* Validate page offsets */
-                    ASSERT_GUEST_MSG_RETURN(   !(pPageListInfo->aPages[0] & GUEST_PAGE_OFFSET_MASK)
-                                            || (pPageListInfo->aPages[0] & GUEST_PAGE_OFFSET_MASK) == pPageListInfo->offFirstPage,
+                    ASSERT_GUEST_MSG_RETURN(   !(pPageListInfo->aPages[0] & VMMDEV_PAGE_OFFSET_MASK)
+                                            || (pPageListInfo->aPages[0] & VMMDEV_PAGE_OFFSET_MASK) == pPageListInfo->offFirstPage,
                                             ("%#RX64 offFirstPage=%#x\n", pPageListInfo->aPages[0], pPageListInfo->offFirstPage),
                                             VERR_INVALID_POINTER);
                     uint32_t const cPages = pPageListInfo->cPages;
                     for (uint32_t iPage = 1; iPage < cPages; iPage++)
-                        ASSERT_GUEST_MSG_RETURN(!(pPageListInfo->aPages[iPage] & GUEST_PAGE_OFFSET_MASK),
+                        ASSERT_GUEST_MSG_RETURN(!(pPageListInfo->aPages[iPage] & VMMDEV_PAGE_OFFSET_MASK),
                                                 ("[%#zx]=%#RX64\n", iPage, pPageListInfo->aPages[iPage]), VERR_INVALID_POINTER);
                     RT_UNTRUSTED_VALIDATED_FENCE();
Index: trunk/src/VBox/Devices/VMMDev/VMMDevState.h
===================================================================
--- trunk/src/VBox/Devices/VMMDev/VMMDevState.h	(revision 100184)
+++ trunk/src/VBox/Devices/VMMDev/VMMDevState.h	(revision 100185)
@@ -268,6 +268,9 @@
     /** FLag whether CPU hotplug events are monitored */
     bool                fCpuHotPlugEventsEnabled;
+    /** Flag whether the VMM device is offering the request ports
+     * over MMIO as well (mainly for ARM at the moment). */
+    bool                fMmioReq;
     /** Alignment padding. */
-    bool                afPadding8[3];
+    bool                afPadding8[2];
     /** CPU hotplug event */
     VMMDevCpuEventType  enmCpuHotPlugEvent;
@@ -406,4 +409,6 @@
     /** Handle for the fast VMM request I/O port (PCI region \#0). */
     IOMIOPORTHANDLE     hIoPortFast;
+    /** Handle for the VMM request MMIO region (PCI region \#3). */
+    IOMMMIOHANDLE       hMmioReq;
     /** Handle for the VMMDev RAM (PCI region \#1). */
     PGMMMIO2HANDLE      hMmio2VMMDevRAM;
@@ -567,5 +572,7 @@
 
 /** The saved state version. */
-#define VMMDEV_SAVED_STATE_VERSION                              VMMDEV_SAVED_STATE_VERSION_VMM_MOUSE_EXTENDED_DATA
+#define VMMDEV_SAVED_STATE_VERSION                              VMMDEV_SAVED_STATE_VERSION_MMIO_ACCESS
+/** Added support to optionally use MMIO instead of PIO for passing requests to the host (mainly for ARM). */
+#define VMMDEV_SAVED_STATE_VERSION_MMIO_ACCESS                  20
 /** The saved state version with VMMDev mouse buttons state and wheel movement data. */
 #define VMMDEV_SAVED_STATE_VERSION_VMM_MOUSE_EXTENDED_DATA      19
