Index: /trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp	(revision 88529)
+++ /trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp	(revision 88530)
@@ -345,4 +345,6 @@
     uint32_t                    u32Padding3;
 
+    /** Critical section protecting the memory regions. */
+    RTCRITSECT                  CritSectMemRegns;
     /** List of memory regions - PLSILOGICMEMREGN. */
     RTLISTANCHORR3              ListMemRegns;
@@ -601,9 +603,76 @@
     pThis->u32DiagMemAddr = 0;
 
-    lsilogicR3ConfigurationPagesFree(pThis, pThisCC);
     lsilogicR3InitializeConfigurationPages(pDevIns, pThis, pThisCC);
 
     /* Mark that we finished performing the reset. */
     pThis->enmState = LSILOGICSTATE_READY;
+    return VINF_SUCCESS;
+}
+
+/**
+ * Allocates the configuration pages based on the device.
+ *
+ * @returns nothing.
+ * @param   pThis    Pointer to the shared LsiLogic device state.
+ * @param   pThisCC  Pointer to the ring-3 LsiLogic device state.
+ */
+static int lsilogicR3ConfigurationPagesAlloc(PLSILOGICSCSI pThis, PLSILOGICSCSICC pThisCC)
+{
+    pThisCC->pConfigurationPages = (PMptConfigurationPagesSupported)RTMemAllocZ(sizeof(MptConfigurationPagesSupported));
+    if (!pThisCC->pConfigurationPages)
+        return VERR_NO_MEMORY;
+
+    if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SAS)
+    {
+        PMptConfigurationPagesSas pPages = &pThisCC->pConfigurationPages->u.SasPages;
+
+        pPages->cbManufacturingPage7 = LSILOGICSCSI_MANUFACTURING7_GET_SIZE(pThis->cPorts);
+        PMptConfigurationPageManufacturing7 pManufacturingPage7 = (PMptConfigurationPageManufacturing7)RTMemAllocZ(pPages->cbManufacturingPage7);
+        AssertPtrReturn(pManufacturingPage7, VERR_NO_MEMORY);
+        pPages->pManufacturingPage7 = pManufacturingPage7;
+
+        /* SAS I/O unit page 0 - Port specific information. */
+        pPages->cbSASIOUnitPage0 = LSILOGICSCSI_SASIOUNIT0_GET_SIZE(pThis->cPorts);
+        PMptConfigurationPageSASIOUnit0 pSASPage0 = (PMptConfigurationPageSASIOUnit0)RTMemAllocZ(pPages->cbSASIOUnitPage0);
+        AssertPtrReturn(pSASPage0, VERR_NO_MEMORY);
+        pPages->pSASIOUnitPage0 = pSASPage0;
+
+        /* SAS I/O unit page 1 - Port specific settings. */
+        pPages->cbSASIOUnitPage1 = LSILOGICSCSI_SASIOUNIT1_GET_SIZE(pThis->cPorts);
+        PMptConfigurationPageSASIOUnit1 pSASPage1 = (PMptConfigurationPageSASIOUnit1)RTMemAllocZ(pPages->cbSASIOUnitPage1);
+        AssertPtrReturn(pSASPage1, VERR_NO_MEMORY);
+        pPages->pSASIOUnitPage1 = pSASPage1;
+
+        pPages->cPHYs  = pThis->cPorts;
+        pPages->paPHYs = (PMptPHY)RTMemAllocZ(pPages->cPHYs * sizeof(MptPHY));
+        AssertPtrReturn(pPages->paPHYs, VERR_NO_MEMORY);
+
+        /* Initialize the PHY configuration */
+        for (unsigned i = 0; i < pThis->cPorts; i++)
+        {
+            /* Settings for present devices. */
+            if (pThisCC->paDeviceStates[i].pDrvBase)
+            {
+                PMptSASDevice pSASDevice = (PMptSASDevice)RTMemAllocZ(sizeof(MptSASDevice));
+                AssertPtrReturn(pSASDevice, VERR_NO_MEMORY);
+
+                /* Link into device list. */
+                if (!pPages->cDevices)
+                {
+                    pPages->pSASDeviceHead = pSASDevice;
+                    pPages->pSASDeviceTail = pSASDevice;
+                    pPages->cDevices = 1;
+                }
+                else
+                {
+                    pSASDevice->pPrev = pPages->pSASDeviceTail;
+                    pPages->pSASDeviceTail->pNext = pSASDevice;
+                    pPages->pSASDeviceTail = pSASDevice;
+                    pPages->cDevices++;
+                }
+            }
+        }
+    }
+
     return VINF_SUCCESS;
 }
@@ -642,7 +711,14 @@
             if (pSasPages->pSASIOUnitPage1)
                 RTMemFree(pSasPages->pSASIOUnitPage1);
+
+            pSasPages->pSASDeviceHead      = NULL;
+            pSasPages->paPHYs              = NULL;
+            pSasPages->pManufacturingPage7 = NULL;
+            pSasPages->pSASIOUnitPage0     = NULL;
+            pSasPages->pSASIOUnitPage1     = NULL;
         }
 
         RTMemFree(pThisCC->pConfigurationPages);
+        pThisCC->pConfigurationPages = NULL;
     }
 }
@@ -884,6 +960,7 @@
 static void lsilogicR3DiagRegDataWrite(PLSILOGICSCSI pThis, PLSILOGICSCSICC pThisCC, uint32_t u32Data)
 {
+    RTCritSectEnter(&pThisCC->CritSectMemRegns);
+
     PLSILOGICMEMREGN pRegion = lsilogicR3MemRegionFindByAddr(pThisCC, pThis->u32DiagMemAddr);
-
     if (pRegion)
     {
@@ -960,4 +1037,5 @@
     /* Memory access is always 32bit big. */
     pThis->u32DiagMemAddr += sizeof(uint32_t);
+    RTCritSectLeave(&pThisCC->CritSectMemRegns);
 }
 
@@ -972,6 +1050,7 @@
 static void lsilogicR3DiagRegDataRead(PLSILOGICSCSI pThis, PLSILOGICSCSICC pThisCC, uint32_t *pu32Data)
 {
+    RTCritSectEnter(&pThisCC->CritSectMemRegns);
+
     PLSILOGICMEMREGN pRegion = lsilogicR3MemRegionFindByAddr(pThisCC, pThis->u32DiagMemAddr);
-
     if (pRegion)
     {
@@ -990,4 +1069,5 @@
     /* Memory access is always 32bit big. */
     pThis->u32DiagMemAddr += sizeof(uint32_t);
+    RTCritSectLeave(&pThisCC->CritSectMemRegns);
 }
 
@@ -1123,4 +1203,5 @@
 
             /* Check for a valid firmware image in the IOC memory which was downloaded by the guest earlier and use that. */
+            RTCritSectEnter(&pThisCC->CritSectMemRegns);
             PLSILOGICMEMREGN pRegion = lsilogicR3MemRegionFindByAddr(pThisCC, LSILOGIC_FWIMGHDR_LOAD_ADDRESS);
             if (pRegion)
@@ -1146,4 +1227,5 @@
                 }
             }
+            RTCritSectLeave(&pThisCC->CritSectMemRegns);
             break;
         }
@@ -3419,7 +3501,7 @@
 
     /* Manufacturing Page 7 - Connector settings. */
-    pPages->cbManufacturingPage7 = LSILOGICSCSI_MANUFACTURING7_GET_SIZE(pThis->cPorts);
-    PMptConfigurationPageManufacturing7 pManufacturingPage7 = (PMptConfigurationPageManufacturing7)RTMemAllocZ(pPages->cbManufacturingPage7);
+    PMptConfigurationPageManufacturing7 pManufacturingPage7 = pPages->pManufacturingPage7;
     AssertPtr(pManufacturingPage7);
+
     MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(pManufacturingPage7,
                                               0, 7,
@@ -3431,9 +3513,7 @@
         pManufacturingPage7->u.fields.Header.u8PageLength = pPages->cbManufacturingPage7 / 4;
     pManufacturingPage7->u.fields.u8NumPhys = pThis->cPorts;
-    pPages->pManufacturingPage7 = pManufacturingPage7;
 
     /* SAS I/O unit page 0 - Port specific information. */
-    pPages->cbSASIOUnitPage0 = LSILOGICSCSI_SASIOUNIT0_GET_SIZE(pThis->cPorts);
-    PMptConfigurationPageSASIOUnit0 pSASPage0 = (PMptConfigurationPageSASIOUnit0)RTMemAllocZ(pPages->cbSASIOUnitPage0);
+    PMptConfigurationPageSASIOUnit0 pSASPage0 = pPages->pSASIOUnitPage0;
     AssertPtr(pSASPage0);
 
@@ -3445,6 +3525,5 @@
 
     /* SAS I/O unit page 1 - Port specific settings. */
-    pPages->cbSASIOUnitPage1 = LSILOGICSCSI_SASIOUNIT1_GET_SIZE(pThis->cPorts);
-    PMptConfigurationPageSASIOUnit1 pSASPage1 = (PMptConfigurationPageSASIOUnit1)RTMemAllocZ(pPages->cbSASIOUnitPage1);
+    PMptConfigurationPageSASIOUnit1 pSASPage1 = pPages->pSASIOUnitPage1;
     AssertPtr(pSASPage1);
 
@@ -3455,5 +3534,4 @@
     pSASPage1->u.fields.u16ControlFlags = 0;
     pSASPage1->u.fields.u16AdditionalControlFlags = 0;
-    pPages->pSASIOUnitPage1 = pSASPage1;
 
     /* SAS I/O unit page 2 - Port specific information. */
@@ -3471,9 +3549,9 @@
     pPages->SASIOUnitPage3.u.fields.ExtHeader.u16ExtPageLength = sizeof(MptConfigurationPageSASIOUnit3) / 4;
 
-    pPages->cPHYs  = pThis->cPorts;
-    pPages->paPHYs = (PMptPHY)RTMemAllocZ(pPages->cPHYs * sizeof(MptPHY));
+    Assert(pPages->cPHYs == pThis->cPorts);
     AssertPtr(pPages->paPHYs);
 
     /* Initialize the PHY configuration */
+    PMptSASDevice pSASDevice = pPages->pSASDeviceHead;
     for (unsigned i = 0; i < pThis->cPorts; i++)
     {
@@ -3524,5 +3602,4 @@
             uint16_t u16DeviceHandle = lsilogicGetHandle(pThis);
             SASADDRESS SASAddress;
-            PMptSASDevice pSASDevice = (PMptSASDevice)RTMemAllocZ(sizeof(MptSASDevice));
             AssertPtr(pSASDevice);
 
@@ -3582,18 +3659,5 @@
             pSASDevice->SASDevicePage2.u.fields.SASAddress                 = SASAddress;
 
-            /* Link into device list. */
-            if (!pPages->cDevices)
-            {
-                pPages->pSASDeviceHead = pSASDevice;
-                pPages->pSASDeviceTail = pSASDevice;
-                pPages->cDevices = 1;
-            }
-            else
-            {
-                pSASDevice->pPrev = pPages->pSASDeviceTail;
-                pPages->pSASDeviceTail->pNext = pSASDevice;
-                pPages->pSASDeviceTail = pSASDevice;
-                pPages->cDevices++;
-            }
+            pSASDevice = pSASDevice->pNext;
         }
     }
@@ -3611,13 +3675,10 @@
 {
     /* Initialize the common pages. */
-    PMptConfigurationPagesSupported pPages = (PMptConfigurationPagesSupported)RTMemAllocZ(sizeof(MptConfigurationPagesSupported));
-    /** @todo r=bird: Missing alloc failure check.   Why do we allocate this
-     *        structure? It's fixed size... */
-
-    pThisCC->pConfigurationPages = pPages;
 
     LogFlowFunc(("pThis=%#p\n", pThis));
 
     /* Clear everything first. */
+    AssertPtrReturnVoid(pThisCC->pConfigurationPages);
+    PMptConfigurationPagesSupported pPages = pThisCC->pConfigurationPages;
     memset(pPages, 0, sizeof(MptConfigurationPagesSupported));
 
@@ -5148,4 +5209,7 @@
     PDMDevHlpCritSectDelete(pDevIns, &pThis->ReplyFreeQueueWriteCritSect);
 
+    if (RTCritSectIsInitialized(&pThisCC->CritSectMemRegns))
+        RTCritSectDelete(&pThisCC->CritSectMemRegns);
+
     RTMemFree(pThisCC->paDeviceStates);
     pThisCC->paDeviceStates = NULL;
@@ -5310,4 +5374,11 @@
     if (RT_FAILURE(rc))
         return PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic: cannot create critical section for reply free queue write access"));
+
+    /*
+     * Critical section protecting the memory regions.
+     */
+    rc = RTCritSectInit(&pThisCC->CritSectMemRegns);
+    if (RT_FAILURE(rc))
+        return PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic: Failed to initialize critical section protecting the memory regions"));
 
     /*
@@ -5534,4 +5605,9 @@
                               ? "LsiLogic SPI info."
                               : "LsiLogic SAS info.", lsilogicR3Info);
+
+    /* Allocate configuration pages. */
+    rc = lsilogicR3ConfigurationPagesAlloc(pThis, pThisCC);
+    if (RT_FAILURE(rc))
+        PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic: Failed to allocate memory for configuration pages"));
 
     /* Perform hard reset. */
