Index: /trunk/include/VBox/vmm/pdmpcidev.h
===================================================================
--- /trunk/include/VBox/vmm/pdmpcidev.h	(revision 65300)
+++ /trunk/include/VBox/vmm/pdmpcidev.h	(revision 65301)
@@ -81,5 +81,5 @@
  * @param   pDevIns         Pointer to the device instance the PCI device
  *                          belongs to.
- * @param   pPciDev         Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
+ * @param   pPciDev         Pointer to the PCI device.
  * @param   iRegion         The region number.
  * @param   GCPhysAddress   Physical address of the region. If enmType is PCI_ADDRESS_SPACE_IO, this
@@ -100,4 +100,20 @@
 /** Pointer to a FNPCIIOREGIONMAP() function. */
 typedef FNPCIIOREGIONMAP *PFNPCIIOREGIONMAP;
+
+
+/**
+ * Sets the size and type for old saved states from within a
+ * PDMPCIDEV::pfnRegionLoadChangeHookR3 callback.
+ *
+ * @returns VBox status code.
+ * @param   pPciDev         Pointer to the PCI device.
+ * @param   iRegion         The region number.
+ * @param   cbRegion        The region size.
+ * @param   enmType         Combination of the PCI_ADDRESS_SPACE_* values.
+ */
+typedef DECLCALLBACK(int) FNPCIIOREGIONOLDSETTER(PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS cbRegion, PCIADDRESSSPACE enmType);
+/** Pointer to a FNPCIIOREGIONOLDSETTER() function. */
+typedef FNPCIIOREGIONOLDSETTER *PFNPCIIOREGIONOLDSETTER;
+
 
 
@@ -142,7 +158,32 @@
     /** Device name. */
     R3PTRTYPE(const char *) pszNameR3;
-    /** Reserved. */
-    RTR3PTR                 pvReserved;
     /** @} */
+
+    /**
+     * Callback for dealing with size changes.
+     *
+     * This is set by the PCI device when needed.  It is only needed if any changes
+     * in the PCI resources have been made that may be incompatible with saved state
+     * (i.e. does not reflect configuration, but configuration defaults changed).
+     *
+     * The implementation can use PDMDevHlpMMIOExReduce to adjust the resource
+     * allocation down in size.  There is currently no way of growing resources.
+     * Dropping a resource is automatic.
+     *
+     * @returns VBox status code.
+     * @param   pDevIns         Pointer to the device instance the PCI device
+     *                          belongs to.
+     * @param   pPciDev         Pointer to the PCI device.
+     * @param   iRegion         The region number or UINT32_MAX if old saved state call.
+     * @param   cbRegion        The size being loaded, RTGCPHYS_MAX if old saved state
+     *                          call, or 0 for dummy 64-bit top half region.
+     * @param   enmType         The type being loaded, -1 if old saved state call, or
+     *                          0xff if dummy 64-bit top half region.
+     * @param   pfnOldSetter    Callback for setting size and type for call
+     *                          regarding old saved states.  NULL otherwise.
+     */
+    DECLR3CALLBACKMEMBER(int, pfnRegionLoadChangeHookR3,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
+                                                         uint64_t cbRegion, PCIADDRESSSPACE enmType,
+                                                         PFNPCIIOREGIONOLDSETTER pfnOldSetter));
 } PDMPCIDEV;
 #ifdef PDMPCIDEVINT_DECLARED
Index: /trunk/src/VBox/Devices/Bus/DevPCI.cpp
===================================================================
--- /trunk/src/VBox/Devices/Bus/DevPCI.cpp	(revision 65300)
+++ /trunk/src/VBox/Devices/Bus/DevPCI.cpp	(revision 65301)
@@ -68,8 +68,13 @@
 *   Defined Constants And Macros                                                                                                 *
 *********************************************************************************************************************************/
-/** @def VBOX_PCI_SAVED_STATE_VERSION
- * Saved state version of the PCI bus device.
- */
-#define VBOX_PCI_SAVED_STATE_VERSION 3
+/** Saved state version of the PCI bus device. */
+#define VBOX_PCI_SAVED_STATE_VERSION                VBOX_PCI_SAVED_STATE_VERSION_REGION_SIZES
+/** Adds I/O region types and sizes for dealing changes in resource regions. */
+#define VBOX_PCI_SAVED_STATE_VERSION_REGION_SIZES   4
+/** Before region sizes, the first named one.
+ * Looking at the code though, we support even older version.  */
+#define VBOX_PCI_SAVED_STATE_VERSION_IRQ_STATES     3
+/** Notes whether we use the I/O APIC. */
+#define VBOX_PCI_SAVED_STATE_VERSION_USE_IO_APIC    2
 
 
@@ -886,7 +891,12 @@
             SSMR3PutMem(pSSM, pDev->abConfig, sizeof(pDev->abConfig));
 
-            int rc = SSMR3PutS32(pSSM, pDev->Int.s.uIrqPinState);
-            if (RT_FAILURE(rc))
-                return rc;
+            SSMR3PutS32(pSSM, pDev->Int.s.uIrqPinState);
+
+            /* Save the type an size of all the regions. */
+            for (uint32_t iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
+            {
+                SSMR3PutU8(pSSM, pDev->Int.s.aIORegions[iRegion].type);
+                SSMR3PutU64(pSSM, pDev->Int.s.aIORegions[iRegion].size);
+            }
         }
     }
@@ -971,12 +981,9 @@
     for (i = 0;; i++)
     {
-        PDMPCIDEV   DevTmp;
-        PPDMPCIDEV  pDev;
-
         /* index / terminator */
         rc = SSMR3GetU32(pSSM, &u32);
         if (RT_FAILURE(rc))
             return rc;
-        if (u32 == (uint32_t)~0)
+        if (u32 == UINT32_MAX)
             break;
         if (    u32 >= RT_ELEMENTS(pBus->apDevices)
@@ -1001,7 +1008,9 @@
 
         /* get the data */
+        PDMPCIDEV DevTmp;
+        RT_ZERO(DevTmp);
         DevTmp.Int.s.uIrqPinState = ~0; /* Invalid value in case we have an older saved state to force a state change in pciSetIrq. */
         SSMR3GetMem(pSSM, DevTmp.abConfig, sizeof(DevTmp.abConfig));
-        if (uVersion < 3)
+        if (uVersion < VBOX_PCI_SAVED_STATE_VERSION_IRQ_STATES)
         {
             int32_t i32Temp;
@@ -1018,6 +1027,17 @@
         }
 
+        /* Load the region types and sizes. */
+        if (uVersion >= VBOX_PCI_SAVED_STATE_VERSION_REGION_SIZES)
+        {
+            for (uint32_t iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
+            {
+                SSMR3GetU8(pSSM, &DevTmp.Int.s.aIORegions[iRegion].type);
+                rc = SSMR3GetU64(pSSM, &DevTmp.Int.s.aIORegions[iRegion].size);
+                AssertLogRelRCReturn(rc, rc);
+            }
+        }
+
         /* check that it's still around. */
-        pDev = pBus->apDevices[i];
+        PPDMPCIDEV pDev = pBus->apDevices[i];
         if (!pDev)
         {
@@ -1033,8 +1053,13 @@
         if (   DevTmp.abConfig[0] != pDev->abConfig[0]
             || DevTmp.abConfig[1] != pDev->abConfig[1])
-            return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x (%s) vendor id mismatch! saved=%.4Rhxs current=%.4Rhxs"),
+            return SSMR3SetCfgError(pSSM, RT_SRC_POS,
+                                    N_("Device in slot %#x (%s) vendor id mismatch! saved=%.4Rhxs current=%.4Rhxs"),
                                     i, pDev->pszNameR3, DevTmp.abConfig, pDev->abConfig);
 
         /* commit the loaded device config. */
+        rc = devpciR3CommonRestoreRegions(pSSM, pDev, DevTmp.Int.s.aIORegions,
+                                          uVersion >= VBOX_PCI_SAVED_STATE_VERSION_REGION_SIZES);
+        if (RT_FAILURE(rc))
+            break;
         devpciR3CommonRestoreConfig(pDev, &DevTmp.abConfig[0]);
 
@@ -1067,9 +1092,9 @@
      */
     SSMR3GetU32(pSSM, &pThis->uConfigReg);
-    if (uVersion > 1)
+    if (uVersion >= VBOX_PCI_SAVED_STATE_VERSION_USE_IO_APIC)
         SSMR3GetBool(pSSM, &pThis->fUseIoApic);
 
     /* Load IRQ states. */
-    if (uVersion > 2)
+    if (uVersion >= VBOX_PCI_SAVED_STATE_VERSION_IRQ_STATES)
     {
         for (uint8_t i = 0; i < RT_ELEMENTS(pThis->Piix3.auPciLegacyIrqLevels); i++)
@@ -1086,5 +1111,5 @@
     if (RT_FAILURE(rc))
         return rc;
-    if (u32 != (uint32_t)~0)
+    if (u32 != UINT32_MAX)
         AssertMsgFailedReturn(("u32=%#x\n", u32), rc);
 
Index: /trunk/src/VBox/Devices/Bus/DevPciIch9.cpp
===================================================================
--- /trunk/src/VBox/Devices/Bus/DevPciIch9.cpp	(revision 65300)
+++ /trunk/src/VBox/Devices/Bus/DevPciIch9.cpp	(revision 65301)
@@ -74,10 +74,13 @@
 *   Defined Constants And Macros                                                                                                 *
 *********************************************************************************************************************************/
-/** @def VBOX_ICH9PCI_SAVED_STATE_VERSION_CURRENT
- * Saved state version of the ICH9 PCI bus device.
- */
-#define VBOX_ICH9PCI_SAVED_STATE_VERSION_NOMSI 1
-#define VBOX_ICH9PCI_SAVED_STATE_VERSION_MSI   2
-#define VBOX_ICH9PCI_SAVED_STATE_VERSION_CURRENT VBOX_ICH9PCI_SAVED_STATE_VERSION_MSI
+/** Saved state version of the ICH9 PCI bus device. */
+#define VBOX_ICH9PCI_SAVED_STATE_VERSION                VBOX_ICH9PCI_SAVED_STATE_VERSION_REGION_SIZES
+/** Adds I/O region types and sizes for dealing changes in resource regions. */
+#define VBOX_ICH9PCI_SAVED_STATE_VERSION_REGION_SIZES   3
+/** This appears to be the first state we need to care about. */
+#define VBOX_ICH9PCI_SAVED_STATE_VERSION_MSI            2
+/** This is apparently not supported or has a grossly incomplete state, juding
+ * from hints in the code. */
+#define VBOX_ICH9PCI_SAVED_STATE_VERSION_NOMSI          1
 
 /** Invalid PCI region mapping address. */
@@ -918,4 +921,5 @@
             if (RT_FAILURE(rc))
                 return rc;
+
             /* Save MSI-X page state */
             if (pDev->Int.s.u8MsixCapOffset != 0)
@@ -925,4 +929,12 @@
                 if (RT_FAILURE(rc))
                     return rc;
+            }
+
+            /* Save the type an size of all the regions. */
+            for (uint32_t iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
+            {
+                SSMR3PutU8(pSSM, pDev->Int.s.aIORegions[iRegion].type);
+                rc = SSMR3PutU64(pSSM, pDev->Int.s.aIORegions[iRegion].size);
+                AssertRCReturn(rc, rc);
             }
         }
@@ -1198,4 +1210,73 @@
 }
 
+
+/**
+ * @callback_method_impl{FNPCIIOREGIONOLDSETTER}
+ */
+static DECLCALLBACK(int) devpciR3CommonRestoreOldSetRegion(PPDMPCIDEV pPciDev, uint32_t iRegion,
+                                                           RTGCPHYS cbRegion, PCIADDRESSSPACE enmType)
+{
+    AssertLogRelReturn(iRegion < RT_ELEMENTS(pPciDev->Int.s.aIORegions), VERR_INVALID_PARAMETER);
+    pPciDev->Int.s.aIORegions[iRegion].type = enmType;
+    pPciDev->Int.s.aIORegions[iRegion].size = cbRegion;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Checks for and deals with changes in resource sizes and types.
+ *
+ * @returns VBox status code.
+ * @param   pSSM                The Saved state handle.
+ * @param   pPciDev             The PCI device in question.
+ * @param   paIoRegions         I/O regions with the size and type fields from
+ *                              the saved state.
+ * @param   fNewState           Set if this is a new state with I/O region sizes
+ *                              and types, clear if old one.
+ */
+int devpciR3CommonRestoreRegions(PSSMHANDLE pSSM, PPDMPCIDEV pPciDev, PPCIIOREGION paIoRegions, bool fNewState)
+{
+    int rc;
+    if (fNewState)
+    {
+        for (uint32_t iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
+        {
+            if (   pPciDev->Int.s.aIORegions[iRegion].type != paIoRegions[iRegion].type
+                || pPciDev->Int.s.aIORegions[iRegion].size != paIoRegions[iRegion].size)
+            {
+                AssertLogRelMsgFailed(("PCI: %8s/%u: region #%u size/type load change: %#RGp/%#x -> %#RGp/%#x\n",
+                                       pPciDev->pszNameR3, pPciDev->Int.s.CTX_SUFF(pDevIns)->iInstance,
+                                       pPciDev->Int.s.aIORegions[iRegion].size, pPciDev->Int.s.aIORegions[iRegion].type,
+                                       paIoRegions[iRegion].size, paIoRegions[iRegion].type));
+                if (pPciDev->pfnRegionLoadChangeHookR3)
+                {
+                    rc = pPciDev->pfnRegionLoadChangeHookR3(pPciDev->Int.s.pDevInsR3, pPciDev, iRegion, paIoRegions[iRegion].size,
+                                                            (PCIADDRESSSPACE)paIoRegions[iRegion].type, NULL /*pfnOldSetter*/);
+                    if (RT_FAILURE(rc))
+                        return SSMR3SetLoadError(pSSM, rc, RT_SRC_POS,
+                                                 N_("Device %s/%u failed to respond to region #%u size/type changing from %#RGp/%#x to %#RGp/%#x: %Rrc"),
+                                                 pPciDev->pszNameR3, pPciDev->Int.s.CTX_SUFF(pDevIns)->iInstance, iRegion,
+                                                 pPciDev->Int.s.aIORegions[iRegion].size, pPciDev->Int.s.aIORegions[iRegion].type,
+                                                 paIoRegions[iRegion].size, paIoRegions[iRegion].type, rc);
+                }
+                pPciDev->Int.s.aIORegions[iRegion].type = paIoRegions[iRegion].type;
+                pPciDev->Int.s.aIORegions[iRegion].size = paIoRegions[iRegion].size;
+            }
+        }
+    }
+    /* Old saved state without sizes and types.  Do a special hook call to give
+       devices with changes a chance to adjust resources back to old values. */
+    else if (pPciDev->pfnRegionLoadChangeHookR3)
+    {
+        rc = pPciDev->pfnRegionLoadChangeHookR3(pPciDev->Int.s.pDevInsR3, pPciDev, UINT32_MAX, RTGCPHYS_MAX, (PCIADDRESSSPACE)-1,
+                                                devpciR3CommonRestoreOldSetRegion);
+        if (RT_FAILURE(rc))
+            return SSMR3SetLoadError(pSSM, rc, RT_SRC_POS,  N_("Device %s/%u failed to resize its resources: %Rrc"),
+                                     pPciDev->pszNameR3, pPciDev->Int.s.CTX_SUFF(pDevIns)->iInstance, rc);
+    }
+    return VINF_SUCCESS;
+}
+
+
 /**
  * Common worker for ich9pciR3LoadExec and ich9pcibridgeR3LoadExec.
@@ -1214,5 +1295,6 @@
 
     Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
-    if (uVersion != VBOX_ICH9PCI_SAVED_STATE_VERSION_CURRENT)
+    if (   uVersion < VBOX_ICH9PCI_SAVED_STATE_VERSION_MSI
+        || uVersion > VBOX_ICH9PCI_SAVED_STATE_VERSION)
         return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
 
@@ -1248,7 +1330,4 @@
     for (i = 0;; i++)
     {
-        PPDMPCIDEV  pDev;
-        PDMPCIDEV   DevTmp;
-
         /* index / terminator */
         rc = SSMR3GetU32(pSSM, &u32);
@@ -1260,4 +1339,5 @@
 
         /* skip forward to the device checking that no new devices are present. */
+        PPDMPCIDEV pDev;
         for (; i < u32; i++)
         {
@@ -1281,4 +1361,6 @@
 
         /* get the data */
+        PDMPCIDEV DevTmp;
+        RT_ZERO(DevTmp);
         DevTmp.Int.s.fFlags = 0;
         DevTmp.Int.s.u8MsiCapOffset = 0;
@@ -1307,5 +1389,18 @@
         }
 
-        /* check that it's still around. */
+        /* Load the region types and sizes. */
+        if (uVersion >= VBOX_ICH9PCI_SAVED_STATE_VERSION_REGION_SIZES)
+        {
+            for (uint32_t iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
+            {
+                SSMR3GetU8(pSSM, &DevTmp.Int.s.aIORegions[iRegion].type);
+                rc = SSMR3GetU64(pSSM, &DevTmp.Int.s.aIORegions[iRegion].size);
+                AssertLogRelRCReturn(rc, rc);
+            }
+        }
+
+        /*
+         * Check that it's still around.
+         */
         pDev = pBus->apDevices[i];
         if (!pDev)
@@ -1335,4 +1430,8 @@
 
         /* commit the loaded device config. */
+        rc = devpciR3CommonRestoreRegions(pSSM, pDev, DevTmp.Int.s.aIORegions,
+                                          uVersion >= VBOX_ICH9PCI_SAVED_STATE_VERSION_REGION_SIZES);
+        if (RT_FAILURE(rc))
+            break;
         Assert(!pciDevIsPassthrough(pDev));
         devpciR3CommonRestoreConfig(pDev, &DevTmp.abConfig[0]);
@@ -1363,7 +1462,7 @@
 
     /* We ignore this version as there's no saved state with it anyway */
-    if (uVersion == VBOX_ICH9PCI_SAVED_STATE_VERSION_NOMSI)
+    if (uVersion <= VBOX_ICH9PCI_SAVED_STATE_VERSION_NOMSI)
         return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
-    if (uVersion > VBOX_ICH9PCI_SAVED_STATE_VERSION_MSI)
+    if (uVersion > VBOX_ICH9PCI_SAVED_STATE_VERSION)
         return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
 
@@ -1392,6 +1491,4 @@
 {
     PDEVPCIBUS pThis = PDMINS_2_DATA(pDevIns, PDEVPCIBUS);
-    if (uVersion > VBOX_ICH9PCI_SAVED_STATE_VERSION_MSI)
-        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
     return ich9pciR3CommonLoadExec(pThis, pSSM, uVersion, uPass);
 }
@@ -2730,5 +2827,5 @@
     }
 
-    rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_ICH9PCI_SAVED_STATE_VERSION_CURRENT,
+    rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_ICH9PCI_SAVED_STATE_VERSION,
                                 sizeof(*pBus) + 16*128, "pgm",
                                 NULL, NULL, NULL,
@@ -2972,5 +3069,5 @@
      * to make changes easier.
      */
-    rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_ICH9PCI_SAVED_STATE_VERSION_CURRENT,
+    rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_ICH9PCI_SAVED_STATE_VERSION,
                                 sizeof(*pBus) + 16*128,
                                 "pgm" /* before */,
Index: /trunk/src/VBox/Devices/Bus/DevPciInternal.h
===================================================================
--- /trunk/src/VBox/Devices/Bus/DevPciInternal.h	(revision 65300)
+++ /trunk/src/VBox/Devices/Bus/DevPciInternal.h	(revision 65301)
@@ -194,4 +194,5 @@
                                                         uint32_t uAddress, uint32_t u32Value, unsigned cb);
 void devpciR3CommonRestoreConfig(PPDMPCIDEV pDev, uint8_t const *pbSrcConfig);
+int  devpciR3CommonRestoreRegions(PSSMHANDLE pSSM, PPDMPCIDEV pPciDev, PPCIIOREGION paIoRegions, bool fNewState);
 
 #endif
Index: /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
===================================================================
--- /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp	(revision 65300)
+++ /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp	(revision 65301)
@@ -148,5 +148,5 @@
     GEN_CHECK_OFF(PDMPCIDEV, uDevFn);
     GEN_CHECK_OFF(PDMPCIDEV, pszNameR3);
-    GEN_CHECK_OFF(PDMPCIDEV, pvReserved);
+    GEN_CHECK_OFF(PDMPCIDEV, pfnRegionLoadChangeHookR3);
     GEN_CHECK_OFF(PDMPCIDEV, Int);
     GEN_CHECK_OFF(PDMPCIDEV, Int.s.aIORegions);
