Index: /trunk/include/VBox/HGSMI/HGSMI.h
===================================================================
--- /trunk/include/VBox/HGSMI/HGSMI.h	(revision 50517)
+++ /trunk/include/VBox/HGSMI/HGSMI.h	(revision 50518)
@@ -228,6 +228,14 @@
                        uintptr_t offDelta,
                        HGSMISIZE cbArea,
+                       HGSMIOFFSET offBase);
+
+int HGSMIHeapRestoreMA(HGSMIHEAP *pHeap,
+                       void *pvBase,
+                       HGSMISIZE cbArea,
                        HGSMIOFFSET offBase,
-                       const HGSMIENV *pEnv);
+                       uint32_t cBlocks,
+                       HGSMIOFFSET *paDescriptors,
+                       HGSMISIZE cbMaxBlock,
+                       HGSMIENV *pEnv);
 
 void HGSMIHeapSetupUninitialized (HGSMIHEAP *pHeap);
@@ -258,14 +266,21 @@
 
 #ifdef IN_RING3
-/* needed for heap relocation */
+/* Needed for heap relocation: offset of the heap handle relative to the start of heap area. */
 DECLINLINE(HGSMIOFFSET) HGSMIHeapHandleLocationOffset(HGSMIHEAP *pHeap)
 {
-#if (__GNUC__ * 100 + __GNUC_MINOR__) < 405
-    /* does not work with gcc-4.5 */
-    AssertCompile((uintptr_t)NIL_RTHEAPSIMPLE == (uintptr_t)NIL_RTHEAPOFFSET);
-#endif
-    return pHeap->u.hPtr != NIL_RTHEAPSIMPLE
-        ? (HGSMIOFFSET)(pHeap->area.pu8Base - (uint8_t*)pHeap->u.hPtr)
-        : HGSMIOFFSET_VOID;
+    HGSMIOFFSET offHeapHandle;
+    if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_POINTER)
+    {
+        offHeapHandle = (HGSMIOFFSET)((uintptr_t)pHeap->u.hPtr - (uintptr_t)pHeap->area.pu8Base);
+    }
+    else if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_OFFSET)
+    {
+        offHeapHandle = (HGSMIOFFSET)((uintptr_t)pHeap->u.hOff - (uintptr_t)pHeap->area.pu8Base);
+    }
+    else
+    {
+        offHeapHandle = HGSMIOFFSET_VOID;
+    }
+    return offHeapHandle;
 }
 #endif /* IN_RING3 */
Index: /trunk/src/VBox/Devices/Graphics/DevVGASavedState.h
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGASavedState.h	(revision 50517)
+++ /trunk/src/VBox/Devices/Graphics/DevVGASavedState.h	(revision 50518)
@@ -23,5 +23,6 @@
 #define Graphics_DevVGASavedState_h
 
-#define VGA_SAVEDSTATE_VERSION              11
+#define VGA_SAVEDSTATE_VERSION              12
+#define VGA_SAVEDSTATE_VERSION_HGSMIMA      12 /* HGSMI memory allocator. */
 #define VGA_SAVEDSTATE_VERSION_VMSVGA       11
 #define VGA_SAVEDSTATE_VERSION_VMSVGA_2D    10 /* <- internal build with 2d state only */
Index: /trunk/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp	(revision 50517)
+++ /trunk/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp	(revision 50518)
@@ -1327,4 +1327,62 @@
 }
 
+static int hgsmiHostSaveMA(PSSMHANDLE pSSM, HGSMIMADATA *pMA)
+{
+    int rc = SSMR3PutU32(pSSM, pMA->cBlocks);
+    if (RT_SUCCESS(rc))
+    {
+        HGSMIMABLOCK *pIter;
+        RTListForEach(&pMA->listBlocks, pIter, HGSMIMABLOCK, nodeBlock)
+        {
+            SSMR3PutU32(pSSM, pIter->descriptor);
+        }
+
+        rc = SSMR3PutU32(pSSM, pMA->cbMaxBlock);
+    }
+
+    return rc;
+}
+
+static int hgsmiHostLoadMA(PSSMHANDLE pSSM, uint32_t *pcBlocks, HGSMIOFFSET **ppaDescriptors, HGSMISIZE *pcbMaxBlock)
+{
+    int rc = SSMR3GetU32(pSSM, pcBlocks);
+    if (RT_SUCCESS(rc))
+    {
+        HGSMIOFFSET *paDescriptors = NULL;
+        if (*pcBlocks > 0)
+        {
+            paDescriptors = (HGSMIOFFSET *)RTMemAlloc(*pcBlocks * sizeof(HGSMIOFFSET));
+            if (paDescriptors)
+            {
+                uint32_t i;
+                for (i = 0; i < *pcBlocks; ++i)
+                {
+                    SSMR3GetU32(pSSM, &paDescriptors[i]);
+                }
+            }
+            else
+            {
+                rc = VERR_NO_MEMORY;
+            }
+        }
+
+        if (RT_SUCCESS(rc))
+        {
+            rc = SSMR3GetU32(pSSM, pcbMaxBlock);
+        }
+
+        if (RT_SUCCESS(rc))
+        {
+            *ppaDescriptors = paDescriptors;
+        }
+        else
+        {
+            RTMemFree(paDescriptors);
+        }
+    }
+
+    return rc;
+}
+
 int HGSMIHostSaveStateExec (PHGSMIINSTANCE pIns, PSSMHANDLE pSSM)
 {
@@ -1332,9 +1390,13 @@
 
     int rc;
+
+    SSMR3PutU32(pSSM, pIns->hostHeap.u32HeapType);
 
     HGSMIOFFSET off = pIns->pHGFlags ? HGSMIPointerToOffset(&pIns->area, (const HGSMIBUFFERHEADER *)pIns->pHGFlags) : HGSMIOFFSET_VOID;
     SSMR3PutU32 (pSSM, off);
 
-    off = HGSMIHeapHandleLocationOffset(&pIns->hostHeap);
+    off = pIns->hostHeap.u32HeapType == HGSMI_HEAP_TYPE_MA?
+              0:
+              HGSMIHeapHandleLocationOffset(&pIns->hostHeap);
     rc = SSMR3PutU32 (pSSM, off);
     if(off != HGSMIOFFSET_VOID)
@@ -1356,4 +1418,12 @@
             hgsmiFIFOUnlock (pIns);
         }
+
+        if (RT_SUCCESS(rc))
+        {
+            if (pIns->hostHeap.u32HeapType == HGSMI_HEAP_TYPE_MA)
+            {
+                rc = hgsmiHostSaveMA(pSSM, &pIns->hostHeap.u.ma);
+            }
+        }
     }
 
@@ -1372,4 +1442,12 @@
     int rc;
     HGSMIOFFSET off;
+    uint32_t u32HeapType = HGSMI_HEAP_TYPE_NULL;
+
+    if (u32Version >= VGA_SAVEDSTATE_VERSION_HGSMIMA)
+    {
+        rc = SSMR3GetU32(pSSM, &u32HeapType);
+        AssertRCReturn(rc, rc);
+    }
+
     rc = SSMR3GetU32(pSSM, &off);
     AssertRCReturn(rc, rc);
@@ -1381,4 +1459,12 @@
     if(off != HGSMIOFFSET_VOID)
     {
+        /* There is a saved heap. */
+        if (u32HeapType == HGSMI_HEAP_TYPE_NULL)
+        {
+            u32HeapType = u32Version > VGA_SAVEDSTATE_VERSION_HOST_HEAP?
+                              HGSMI_HEAP_TYPE_OFFSET:
+                              HGSMI_HEAP_TYPE_POINTER;
+        }
+
         HGSMIOFFSET offHeap;
         SSMR3GetU32(pSSM, &offHeap);
@@ -1388,24 +1474,4 @@
         rc = SSMR3GetU64(pSSM, &oldMem);
         AssertRCReturn(rc, rc);
-
-        rc = hgsmiHostHeapLock (pIns);
-        if (RT_SUCCESS (rc))
-        {
-            Assert(!pIns->hostHeap.cRefs);
-            pIns->hostHeap.cRefs = 0;
-
-            rc = HGSMIHeapRelocate(&pIns->hostHeap,
-                                   u32Version > VGA_SAVEDSTATE_VERSION_HOST_HEAP?
-                                       HGSMI_HEAP_TYPE_OFFSET:
-                                       HGSMI_HEAP_TYPE_POINTER,
-                                   pIns->area.pu8Base+offHeap,
-                                   off,
-                                   uintptr_t(pIns->area.pu8Base) - uintptr_t(oldMem),
-                                   cbHeap,
-                                   offHeap,
-                                   &g_hgsmiEnv);
-
-            hgsmiHostHeapUnlock (pIns);
-        }
 
         if (RT_SUCCESS(rc))
@@ -1425,4 +1491,48 @@
 
                 hgsmiFIFOUnlock (pIns);
+            }
+        }
+
+        if (RT_SUCCESS(rc))
+        {
+            if (u32HeapType == HGSMI_HEAP_TYPE_MA)
+            {
+                uint32_t cBlocks = 0;
+                HGSMISIZE cbMaxBlock = 0;
+                HGSMIOFFSET *paDescriptors = NULL;
+                rc = hgsmiHostLoadMA(pSSM, &cBlocks, &paDescriptors, &cbMaxBlock);
+                if (RT_SUCCESS(rc))
+                {
+                    rc = HGSMIHeapRestoreMA(&pIns->hostHeap,
+                                            pIns->area.pu8Base+offHeap,
+                                            cbHeap,
+                                            offHeap,
+                                            cBlocks,
+                                            paDescriptors,
+                                            cbMaxBlock,
+                                            &g_hgsmiEnv);
+
+                    RTMemFree(paDescriptors);
+                }
+            }
+            else if (   u32HeapType == HGSMI_HEAP_TYPE_OFFSET
+                     || u32HeapType == HGSMI_HEAP_TYPE_POINTER)
+            {
+                rc = hgsmiHostHeapLock (pIns);
+                if (RT_SUCCESS (rc))
+                {
+                    Assert(!pIns->hostHeap.cRefs);
+                    pIns->hostHeap.cRefs = 0;
+
+                    rc = HGSMIHeapRelocate(&pIns->hostHeap,
+                                           u32HeapType,
+                                           pIns->area.pu8Base+offHeap,
+                                           off,
+                                           uintptr_t(pIns->area.pu8Base) - uintptr_t(oldMem),
+                                           cbHeap,
+                                           offHeap);
+
+                    hgsmiHostHeapUnlock (pIns);
+                }
             }
         }
@@ -1748,4 +1858,6 @@
 #endif
 
+    HGSMIHeapDestroy(&pIns->hostHeap);
+
     HGSMIHeapSetupUninitialized(&pIns->hostHeap);
 
@@ -1759,4 +1871,6 @@
     if (pIns)
     {
+        HGSMIHeapDestroy(&pIns->hostHeap);
+
         if (RTCritSectIsInitialized (&pIns->hostHeapCritSect))
         {
Index: /trunk/src/VBox/GuestHost/HGSMI/HGSMICommon.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/HGSMI/HGSMICommon.cpp	(revision 50517)
+++ /trunk/src/VBox/GuestHost/HGSMI/HGSMICommon.cpp	(revision 50518)
@@ -201,6 +201,5 @@
                        uintptr_t offDelta,
                        HGSMISIZE cbArea,
-                       HGSMIOFFSET offBase,
-                       const HGSMIENV *pEnv)
+                       HGSMIOFFSET offBase)
 {
     if (   !pHeap
@@ -214,10 +213,5 @@
     if (RT_SUCCESS (rc))
     {
-        if (u32HeapType == HGSMI_HEAP_TYPE_MA)
-        {
-            /* @todo rc = HGSMIMAInit(&pHeap->u.ma, &pHeap->area, NULL, 0, 0, pEnv); */
-            rc = VERR_NOT_IMPLEMENTED;
-        }
-        else if (u32HeapType == HGSMI_HEAP_TYPE_OFFSET)
+        if (u32HeapType == HGSMI_HEAP_TYPE_OFFSET)
         {
             pHeap->u.hOff = (RTHEAPOFFSET)((uint8_t *)pvBase + offHeapHandle);
@@ -230,4 +224,5 @@
         else
         {
+            /* HGSMI_HEAP_TYPE_MA does not need the relocation. */
             rc = VERR_NOT_SUPPORTED;
         }
@@ -241,4 +236,33 @@
         {
             HGSMIAreaClear (&pHeap->area);
+        }
+    }
+
+    return rc;
+}
+
+int HGSMIHeapRestoreMA(HGSMIHEAP *pHeap,
+                       void *pvBase,
+                       HGSMISIZE cbArea,
+                       HGSMIOFFSET offBase,
+                       uint32_t cBlocks,
+                       HGSMIOFFSET *paDescriptors,
+                       HGSMISIZE cbMaxBlock,
+                       HGSMIENV *pEnv)
+{
+    int rc = HGSMIAreaInitialize(&pHeap->area, pvBase, cbArea, offBase);
+
+    if (RT_SUCCESS (rc))
+    {
+        rc = HGSMIMAInit(&pHeap->u.ma, &pHeap->area, paDescriptors, cBlocks, cbMaxBlock, pEnv);
+
+        if (RT_SUCCESS(rc))
+        {
+            pHeap->cRefs = 0;
+            pHeap->u32HeapType = HGSMI_HEAP_TYPE_MA;
+        }
+        else
+        {
+            HGSMIAreaClear(&pHeap->area);
         }
     }
