Index: /trunk/include/VBox/VMMDev.h
===================================================================
--- /trunk/include/VBox/VMMDev.h	(revision 76195)
+++ /trunk/include/VBox/VMMDev.h	(revision 76196)
@@ -541,9 +541,11 @@
  * @{ */
 /** Physical page lists are supported by HGCM. */
-#define VMMDEV_HVF_HGCM_PHYS_PAGE_LIST      RT_BIT_32(0)
+#define VMMDEV_HVF_HGCM_PHYS_PAGE_LIST          RT_BIT_32(0)
 /** HGCM supports the embedded buffer parameter type. */
-#define VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS    RT_BIT_32(1)
+#define VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS        RT_BIT_32(1)
+/** HGCM supports the contiguous page list parameter type. */
+#define VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST    RT_BIT_32(2)
 /** VMMDev supports fast IRQ acknowledgements. */
-#define VMMDEV_HVF_FAST_IRQ_ACK             RT_BIT_32(31)
+#define VMMDEV_HVF_FAST_IRQ_ACK                 RT_BIT_32(31)
 /** @} */
 
Index: /trunk/include/VBox/VMMDevCoreTypes.h
===================================================================
--- /trunk/include/VBox/VMMDevCoreTypes.h	(revision 76195)
+++ /trunk/include/VBox/VMMDevCoreTypes.h	(revision 76196)
@@ -275,4 +275,5 @@
     VMMDevHGCMParmType_PageList           = 10, /**< Physical addresses of locked pages for a buffer. */
     VMMDevHGCMParmType_Embedded           = 11, /**< Small buffer embedded in request. */
+    VMMDevHGCMParmType_ContiguousPageList = 12, /**< Like PageList but with physically contiguous memory, so only one page entry. */
     VMMDevHGCMParmType_SizeHack           = 0x7fffffff
 } HGCMFunctionParameterType;
Index: /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibHGCMInternal.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibHGCMInternal.cpp	(revision 76195)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibHGCMInternal.cpp	(revision 76196)
@@ -218,4 +218,5 @@
 
             case VMMDevHGCMParmType_PageList:
+            case VMMDevHGCMParmType_ContiguousPageList:
                 if (fIsUser)
                     return VERR_INVALID_PARAMETER;
@@ -553,5 +554,6 @@
 
             case VMMDevHGCMParmType_PageList:
-                pDstParm->type = VMMDevHGCMParmType_PageList;
+            case VMMDevHGCMParmType_ContiguousPageList:
+                pDstParm->type = pSrcParm->type;
                 pDstParm->u.PageList.size = pSrcParm->u.PageList.size;
                 if (pSrcParm->u.PageList.size)
@@ -857,4 +859,5 @@
 
             case VMMDevHGCMParmType_PageList:
+            case VMMDevHGCMParmType_ContiguousPageList:
                 pDstParm->u.PageList.size = pSrcParm->u.PageList.size;
                 break;
Index: /trunk/src/VBox/Devices/VMMDev/VMMDev.cpp
===================================================================
--- /trunk/src/VBox/Devices/VMMDev/VMMDev.cpp	(revision 76195)
+++ /trunk/src/VBox/Devices/VMMDev/VMMDev.cpp	(revision 76196)
@@ -2299,5 +2299,8 @@
     pReq->build     = RTBldCfgVersionBuild();
     pReq->revision  = RTBldCfgRevision();
-    pReq->features  = VMMDEV_HVF_HGCM_PHYS_PAGE_LIST | VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS | VMMDEV_HVF_FAST_IRQ_ACK;
+    pReq->features  = VMMDEV_HVF_HGCM_PHYS_PAGE_LIST
+                    | VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS
+                    | VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST
+                    | VMMDEV_HVF_FAST_IRQ_ACK;
     return VINF_SUCCESS;
 }
Index: /trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp
===================================================================
--- /trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp	(revision 76195)
+++ /trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp	(revision 76196)
@@ -329,5 +329,6 @@
                     || pGuestParm->enmType == VMMDevHGCMParmType_LinAddr_Out
                     || pGuestParm->enmType == VMMDevHGCMParmType_LinAddr
-                    || pGuestParm->enmType == VMMDevHGCMParmType_PageList)
+                    || pGuestParm->enmType == VMMDevHGCMParmType_PageList
+                    || pGuestParm->enmType == VMMDevHGCMParmType_ContiguousPageList)
                     if (pGuestParm->u.ptr.paPages != &pGuestParm->u.ptr.GCPhysSinglePage)
                         RTMemFree(pGuestParm->u.ptr.paPages);
@@ -667,4 +668,5 @@
             case VMMDevHGCMParmType_PageList:
             case VMMDevHGCMParmType_Embedded:
+            case VMMDevHGCMParmType_ContiguousPageList:
             {
                 const uint32_t cbData = pGuestParm->u.ptr.cbData;
@@ -684,7 +686,18 @@
                         if (pGuestParm->enmType != VMMDevHGCMParmType_Embedded)
                         {
-                            int rc = vmmdevHGCMGuestBufferRead(pThis->pDevInsR3, pv, cbData, &pGuestParm->u.ptr);
-                            ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc);
-                            RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
+                            if (pGuestParm->enmType != VMMDevHGCMParmType_ContiguousPageList)
+                            {
+                                int rc = vmmdevHGCMGuestBufferRead(pThis->pDevInsR3, pv, cbData, &pGuestParm->u.ptr);
+                                ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc);
+                                RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
+                            }
+                            else
+                            {
+                                int rc = PDMDevHlpPhysRead(pThis->pDevInsR3,
+                                                           pGuestParm->u.ptr.paPages[0] | pGuestParm->u.ptr.offFirstPage,
+                                                           pv, cbData);
+                                ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc);
+                                RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
+                            }
                         }
                         else
@@ -898,4 +911,5 @@
 
             case VMMDevHGCMParmType_PageList:
+            case VMMDevHGCMParmType_ContiguousPageList:
             {
 #ifdef VBOX_WITH_64_BITS_GUESTS
@@ -929,4 +943,8 @@
                                     && pPageListInfo->cPages <= cMaxPages,
                                     VERR_INVALID_PARAMETER);
+
+                /* Contiguous page lists only ever have a single page. */
+                ASSERT_GUEST_RETURN(   pPageListInfo->cPages == 1
+                                    || pGuestParm->enmType == VMMDevHGCMParmType_PageList, VERR_INVALID_PARAMETER);
 
                 /* Other fields of PageListInfo. */
@@ -1198,6 +1216,4 @@
     AssertReturn(pCmd->enmCmdType == VBOXHGCMCMDTYPE_CALL, VERR_INTERNAL_ERROR);
 
-    int rc = VINF_SUCCESS;
-
     /*
      * Go over parameter descriptions saved in pCmd.
@@ -1230,9 +1246,11 @@
                 const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
                 if (   pPtr->cbData > 0
-                    && pPtr->fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST)
+                    && (pPtr->fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST))
                 {
                     const void *pvSrc = pHostParm->u.pointer.addr;
                     uint32_t cbSrc = pHostParm->u.pointer.size;
-                    rc = vmmdevHGCMGuestBufferWrite(pThis->pDevInsR3, pPtr, pvSrc, cbSrc);
+                    int rc = vmmdevHGCMGuestBufferWrite(pThis->pDevInsR3, pPtr, pvSrc, cbSrc);
+                    if (RT_FAILURE(rc))
+                        break;
                 }
                 break;
@@ -1254,13 +1272,27 @@
             }
 
+            case VMMDevHGCMParmType_ContiguousPageList:
+            {
+/** @todo Update the return buffer size.  */
+                const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
+                if (   pPtr->cbData > 0
+                    && (pPtr->fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST))
+                {
+                    const void *pvSrc    = pHostParm->u.pointer.addr;
+                    uint32_t    cbSrc    = pHostParm->u.pointer.size;
+                    uint32_t    cbToCopy = RT_MIN(cbSrc, pPtr->cbData);
+                    int rc = PDMDevHlpPhysWrite(pThis->pDevInsR3, pGuestParm->u.ptr.paPages[0], pvSrc, cbToCopy);
+                    if (RT_FAILURE(rc))
+                        break;
+                }
+                break;
+            }
+
             default:
                 break;
         }
-
-        if (RT_FAILURE(rc))
-            break;
-    }
-
-    return rc;
+    }
+
+    return VINF_SUCCESS;
 }
 
@@ -1642,5 +1674,6 @@
                              || pGuestParm->enmType == VMMDevHGCMParmType_LinAddr
                              || pGuestParm->enmType == VMMDevHGCMParmType_PageList
-                             || pGuestParm->enmType == VMMDevHGCMParmType_Embedded)
+                             || pGuestParm->enmType == VMMDevHGCMParmType_Embedded
+                             || pGuestParm->enmType == VMMDevHGCMParmType_ContiguousPageList)
                     {
                         const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
@@ -1776,5 +1809,6 @@
                              || pGuestParm->enmType == VMMDevHGCMParmType_LinAddr
                              || pGuestParm->enmType == VMMDevHGCMParmType_PageList
-                             || pGuestParm->enmType == VMMDevHGCMParmType_Embedded)
+                             || pGuestParm->enmType == VMMDevHGCMParmType_Embedded
+                             || pGuestParm->enmType == VMMDevHGCMParmType_ContiguousPageList)
                     {
                         VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
@@ -1789,5 +1823,6 @@
                             else
                             {
-                                AssertReturn(pGuestParm->enmType != VMMDevHGCMParmType_Embedded, VERR_INTERNAL_ERROR_3);
+                                AssertReturn(   pGuestParm->enmType != VMMDevHGCMParmType_Embedded
+                                             && pGuestParm->enmType != VMMDevHGCMParmType_ContiguousPageList, VERR_INTERNAL_ERROR_3);
                                 pPtr->paPages = (RTGCPHYS *)RTMemAlloc(pPtr->cPages * sizeof(RTGCPHYS));
                                 AssertStmt(pPtr->paPages, rc = VERR_NO_MEMORY);
