Index: /trunk/include/VBox/ssm.h
===================================================================
--- /trunk/include/VBox/ssm.h	(revision 20152)
+++ /trunk/include/VBox/ssm.h	(revision 20153)
@@ -418,5 +418,5 @@
 
 
-VMMR3DECL(int) SSMR3RegisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
+VMMR3DECL(int) SSMR3RegisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess, const char *pszBefore,
     PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
     PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone);
Index: /trunk/src/VBox/Devices/Bus/DevPCI.cpp
===================================================================
--- /trunk/src/VBox/Devices/Bus/DevPCI.cpp	(revision 20152)
+++ /trunk/src/VBox/Devices/Bus/DevPCI.cpp	(revision 20153)
@@ -1276,4 +1276,5 @@
     SSMR3PutU32(pSSMHandle, pThis->uConfigReg);
     SSMR3PutBool(pSSMHandle, pThis->fUseIoApic);
+
     /*
      * Save IRQ states.
@@ -1309,4 +1310,114 @@
 }
 
+
+/**
+ * Common routine for restoring the config registers of a PCI device.
+ *
+ * @param   pDev                The PCI device.
+ * @param   pbSrcConfig         The configuration register values to be loaded.
+ * @param   fIsBridge           Whether this is a bridge device or not.
+ */
+static void pciR3CommonRestoreConfig(PPCIDEVICE pDev, uint8_t const *pbSrcConfig, bool fIsBridge)
+{
+    /* This table defines the fields for normal devices and bridge devices, and
+       the order in which they need to be restored (nothing special there atm). */
+    static const struct PciField
+    {
+        uint8_t     off;
+        uint8_t     cb;
+        uint8_t     fWritable;
+        uint8_t     fBridge;
+        const char *pszName;
+    } s_aFields[] =
+    {
+        /* off,cb,fW,fB, pszName */
+        { 0x00, 2, 0, 3, "VENDOR_ID" },
+        { 0x02, 2, 0, 3, "DEVICE_ID" },
+        { 0x04, 2, 1, 3, "COMMAND" },
+        { 0x06, 2, 1, 3, "STATUS" },
+        { 0x08, 1, 0, 3, "REVISION_ID" },
+        { 0x09, 1, 0, 3, "CLASS_PROG" },
+        { 0x0a, 1, 0, 3, "CLASS_SUB" },
+        { 0x0b, 1, 0, 3, "CLASS_BASE" },
+        { 0x0c, 1, 0, 3, "CACHE_LINE_SIZE" },   // fWritable = ??
+        { 0x0d, 1, 0, 3, "LATENCY_TIMER" },     // fWritable = ??
+        { 0x0e, 1, 0, 3, "HEADER_TYPE" },       // fWritable = ??
+        { 0x0f, 1, 0, 3, "BIST" },              // fWritable = ??
+        { 0x10, 4, 1, 3, "BASE_ADDRESS_0" },
+        { 0x14, 4, 1, 3, "BASE_ADDRESS_1" },
+        { 0x18, 4, 1, 3, "BASE_ADDRESS_2" },
+        { 0x18, 1, 1, 2, "PRIMARY_BUS" },       // fWritable = ??
+        { 0x19, 1, 1, 2, "SECONDARY_BUS" },     // fWritable = ??
+        { 0x1a, 1, 1, 2, "SUBORDINATE_BUS" },   // fWritable = ??
+        { 0x1b, 1, 1, 2, "SEC_LATENCY_TIMER" }, // fWritable = ??
+        { 0x1c, 4, 1, 1, "BASE_ADDRESS_3" },
+        { 0x1c, 1, 1, 2, "IO_BASE" },           // fWritable = ??
+        { 0x1d, 1, 1, 2, "IO_LIMIT" },          // fWritable = ??
+        { 0x1e, 2, 1, 2, "SEC_STATUS" },        // fWritable = ??
+        { 0x20, 4, 1, 1, "BASE_ADDRESS_4" },
+        { 0x20, 2, 1, 2, "MEMORY_BASE" },       // fWritable = ??
+        { 0x22, 2, 1, 2, "MEMORY_LIMIT" },      // fWritable = ??
+        { 0x24, 4, 1, 1, "BASE_ADDRESS_4" },
+        { 0x24, 2, 1, 2, "PREF_MEMORY_BASE" },  // fWritable = ??
+        { 0x26, 2, 1, 2, "PREF_MEMORY_LIMIT" }, // fWritable = ??
+        { 0x28, 4, 1, 1, "CARDBUS_CIS" },       // fWritable = ??
+        { 0x28, 4, 1, 2, "PREF_BASE_UPPER32" }, // fWritable = ??
+        { 0x2c, 2, 0, 1, "SUBSYSTEM_VENDOR_ID" },// fWritable = !?
+        { 0x2c, 4, 1, 2, "PREF_LIMIT_UPPER32" },// fWritable = ??
+        { 0x2e, 2, 0, 1, "SUBSYSTEM_ID" },      // fWritable = !?
+        { 0x30, 4, 1, 1, "ROM_ADDRESS" },       // fWritable = ?!
+        { 0x30, 2, 1, 2, "IO_BASE_UPPER16" },   // fWritable = ?!
+        { 0x32, 2, 1, 2, "IO_LIMIT_UPPER16" },  // fWritable = ?!
+        { 0x34, 4, 0, 3, "CAPABILITY_LIST" },   // fWritable = !? cb=!?
+        { 0x38, 4, 1, 2, "ROM_ADDRESS_BR" },    // fWritable = !? cb=!? fBridge=!?
+        { 0x3c, 1, 1, 3, "INTERRUPT_LINE" },    // fBridge=??
+        { 0x3d, 1, 0, 3, "INTERRUPT_PIN" },     // fBridge=??
+        { 0x3e, 1, 0, 1, "MIN_GNT" },           // fWritable = !?
+        { 0x3e, 1, 1, 2, "BRIDGE_CONTROL" },    // fWritable = !? cb=!?
+        { 0x3f, 1, 1, 3, "MAX_LAT" },           // fWritable = !? fBridge=!?
+    };
+
+    uint8_t const fBridge = fIsBridge ? 2 : 1;
+    uint8_t *pbDstConfig = &pDev->config[0];
+    for (uint32_t i = 0; i < RT_ELEMENTS(s_aFields); i++)
+        if (s_aFields[i].fBridge & fBridge)
+        {
+            uint8_t const   off = s_aFields[i].off;
+            uint8_t const   cb  = s_aFields[i].cb;
+            uint32_t        u32Src;
+            uint32_t        u32Dst;
+            switch (cb)
+            {
+                case 1:
+                    u32Src = pbSrcConfig[off];
+                    u32Dst = pbDstConfig[off];
+                    break;
+                case 2:
+                    u32Src = *(uint16_t const *)&pbSrcConfig[off];
+                    u32Dst = *(uint16_t const *)&pbDstConfig[off];
+                    break;
+                case 4:
+                    u32Src = *(uint32_t const *)&pbSrcConfig[off];
+                    u32Dst = *(uint32_t const *)&pbDstConfig[off];
+                    break;
+                default:
+                    AssertFailed();
+                    continue;
+            }
+
+            if (u32Src != u32Dst)
+            {
+                if (!s_aFields[i].fWritable)
+                    LogRel(("PCI: %8s/%u: %2u-bit field %s: %x -> %x - !READ ONLY!\n",
+                            pDev->name, pDev->pDevIns->iInstance, cb*8, s_aFields[i].pszName, u32Dst, u32Src));
+                else
+                    LogRel(("PCI: %8s/%u: %2u-bit field %s: %x -> %x\n",
+                            pDev->name, pDev->pDevIns->iInstance, cb*8, s_aFields[i].pszName, u32Dst, u32Src));
+                pDev->Int.s.pfnConfigWrite(pDev, off, u32Src, cb);
+            }
+        }
+}
+
+
 /**
  * Loads a saved PCI device state.
@@ -1319,6 +1430,6 @@
 static DECLCALLBACK(int) pciLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
 {
-    PPCIGLOBALS  pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
-    PPCIBUS      pBus  = &pThis->PciBus;
+    PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
+    PPCIBUS     pBus  = &pThis->PciBus;
     uint32_t    u32;
     uint32_t    i;
@@ -1432,5 +1543,5 @@
 
         /* commit the loaded device config. */
-        memcpy(pDev->config, DevTmp.config, sizeof(pDev->config));
+        pciR3CommonRestoreConfig(pDev, &DevTmp.config[0], false ); /** @todo fix bridge fun! */
 
         pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
@@ -1900,6 +2011,6 @@
     }
 
-    rc = PDMDevHlpSSMRegister(pDevIns, "pci", iInstance, VBOX_PCI_SAVED_STATE_VERSION, sizeof(*pBus),
-                              NULL, pciSaveExec, NULL, NULL, pciLoadExec, NULL);
+    rc = SSMR3RegisterDevice(PDMDevHlpGetVM(pDevIns), pDevIns, "pci", iInstance, VBOX_PCI_SAVED_STATE_VERSION, sizeof(*pBus) + 16*128, "pgm",
+                             NULL, pciSaveExec, NULL, NULL, pciLoadExec, NULL);
     if (RT_FAILURE(rc))
         return rc;
@@ -2109,4 +2220,6 @@
     int         rc;
 
+/** @todo r=bird: this is a copy of pciLoadExec. combine the two!  */
+
     /*
      * Check the version.
@@ -2179,5 +2292,5 @@
 
         /* commit the loaded device config. */
-        memcpy(pDev->config, DevTmp.config, sizeof(pDev->config));
+        pciR3CommonRestoreConfig(pDev, &DevTmp.config[0], false ); /** @todo fix bridge fun! */
 
         pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
@@ -2365,6 +2478,6 @@
      * to make changes easier.
      */
-    rc = PDMDevHlpSSMRegister(pDevIns, "pcibridge", iInstance, VBOX_PCI_SAVED_STATE_VERSION, sizeof(*pBus),
-                              NULL, pcibridgeSaveExec, NULL, NULL, pcibridgeLoadExec, NULL);
+    rc = SSMR3RegisterDevice(PDMDevHlpGetVM(pDevIns), pDevIns, "pcibridge", iInstance, VBOX_PCI_SAVED_STATE_VERSION, sizeof(*pBus) + 16*128, "pgm",
+                             NULL, pcibridgeSaveExec, NULL, NULL, pcibridgeLoadExec, NULL);
     if (RT_FAILURE(rc))
         return rc;
Index: /trunk/src/VBox/VMM/PDMDevHlp.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDMDevHlp.cpp	(revision 20152)
+++ /trunk/src/VBox/VMM/PDMDevHlp.cpp	(revision 20153)
@@ -371,5 +371,5 @@
              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, u32Instance, u32Version, cbGuess, pfnSavePrep, pfnSaveExec, pfnSaveDone, pfnLoadPrep, pfnLoadExec, pfnLoadDone));
 
-    int rc = SSMR3RegisterDevice(pDevIns->Internal.s.pVMR3, pDevIns, pszName, u32Instance, u32Version, cbGuess,
+    int rc = SSMR3RegisterDevice(pDevIns->Internal.s.pVMR3, pDevIns, pszName, u32Instance, u32Version, cbGuess, NULL,
                                  pfnSavePrep, pfnSaveExec, pfnSaveDone,
                                  pfnLoadPrep, pfnLoadExec, pfnLoadDone);
Index: /trunk/src/VBox/VMM/SSM.cpp
===================================================================
--- /trunk/src/VBox/VMM/SSM.cpp	(revision 20152)
+++ /trunk/src/VBox/VMM/SSM.cpp	(revision 20153)
@@ -45,7 +45,6 @@
  * There are plans to extend SSM to make it easier to be both backwards and
  * (somewhat) forwards compatible.  One of the new features will be being able
- * to classify units and data items as unimportant, one example where this would
- * be nice can be seen in with the SSM data unit.  Another potentail feature is
- * naming data items, perhaps by extending the SSMR3PutStruct API.
+ * to classify units and data items as unimportant.  Another potentail feature
+ * is naming data items, perhaps by extending the SSMR3PutStruct API.
  *
  */
@@ -297,5 +296,5 @@
 static DECLCALLBACK(int)    ssmR3SelfSaveExec(PVM pVM, PSSMHANDLE pSSM);
 static DECLCALLBACK(int)    ssmR3SelfLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
-static int                  ssmR3Register(PVM pVM, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess, PSSMUNIT *ppUnit);
+static int                  ssmR3Register(PVM pVM, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess, const char *pszBefore, PSSMUNIT *ppUnit);
 static int                  ssmR3CalcChecksum(RTFILE File, uint64_t cbFile, uint32_t *pu32CRC);
 static void                 ssmR3Progress(PSSMHANDLE pSSM, uint64_t cbAdvance);
@@ -399,9 +398,16 @@
  * @param   u32Version      The data unit version.
  * @param   cbGuess         The guessed data unit size.
+ * @param   pszBefore       Name of data unit to be placed in front of.
+ *                          Optional.
  * @param   ppUnit          Where to store the insterted unit node.
  *                          Caller must fill in the missing details.
  */
-static int ssmR3Register(PVM pVM, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess, PSSMUNIT *ppUnit)
-{
+static int ssmR3Register(PVM pVM, const char *pszName, uint32_t u32Instance,
+                         uint32_t u32Version, size_t cbGuess, const char *pszBefore, PSSMUNIT *ppUnit)
+{
+    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
+    AssertReturn(*pszName, VERR_INVALID_PARAMETER);
+    AssertReturn(!pszBefore || *pszBefore, VERR_INVALID_PARAMETER);
+
     /*
      * Lazy init.
@@ -416,7 +422,10 @@
      * Walk to the end of the list checking for duplicates as we go.
      */
-    size_t      cchName = strlen(pszName);
-    PSSMUNIT    pUnitPrev = NULL;
-    PSSMUNIT    pUnit = pVM->ssm.s.pHead;
+    size_t      cchBefore       = pszBefore ? strlen(pszBefore) : 0;
+    PSSMUNIT    pUnitBeforePrev = NULL;
+    PSSMUNIT    pUnitBefore     = NULL;
+    size_t      cchName         = strlen(pszName);
+    PSSMUNIT    pUnitPrev       = NULL;
+    PSSMUNIT    pUnit           = pVM->ssm.s.pHead;
     while (pUnit)
     {
@@ -428,4 +437,12 @@
             return VERR_SSM_UNIT_EXISTS;
         }
+        if (    pUnit->cchName == cchBefore
+            &&  !pUnitBefore
+            &&  !memcmp(pUnit->szName, pszBefore, cchBefore))
+        {
+            pUnitBeforePrev = pUnitPrev;
+            pUnitBefore     = pUnit;
+        }
+
         /* next */
         pUnitPrev = pUnit;
@@ -443,8 +460,8 @@
      * Fill in (some) data. (Stuff is zero'ed.)
      */
-    pUnit->u32Version = u32Version;
-    pUnit->u32Instance = u32Instance;
-    pUnit->cbGuess = cbGuess;
-    pUnit->cchName = cchName;
+    pUnit->u32Version   = u32Version;
+    pUnit->u32Instance  = u32Instance;
+    pUnit->cbGuess      = cbGuess;
+    pUnit->cchName      = cchName;
     memcpy(pUnit->szName, pszName, cchName);
 
@@ -452,5 +469,13 @@
      * Insert
      */
-    if (pUnitPrev)
+    if (pUnitBefore)
+    {
+        pUnit->pNext = pUnitBefore;
+        if (pUnitBeforePrev)
+            pUnitBeforePrev->pNext = pUnit;
+        else
+            pVM->ssm.s.pHead       = pUnit;
+    }
+    else if (pUnitPrev)
         pUnitPrev->pNext = pUnit;
     else
@@ -475,4 +500,6 @@
  * @param   cbGuess         The approximate amount of data in the unit.
  *                          Only for progress indicators.
+ * @param   pszBefore       Name of data unit which we should be put in front
+ *                          of. Optional (NULL).
  * @param   pfnSavePrep     Prepare save callback, optional.
  * @param   pfnSaveExec     Execute save callback, optional.
@@ -482,10 +509,10 @@
  * @param   pfnLoadDone     Done load callback, optional.
  */
-VMMR3DECL(int) SSMR3RegisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
+VMMR3DECL(int) SSMR3RegisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess, const char *pszBefore,
     PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
     PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
 {
     PSSMUNIT pUnit;
-    int rc = ssmR3Register(pVM, pszName, u32Instance, u32Version, cbGuess, &pUnit);
+    int rc = ssmR3Register(pVM, pszName, u32Instance, u32Version, cbGuess, pszBefore, &pUnit);
     if (RT_SUCCESS(rc))
     {
@@ -528,5 +555,5 @@
 {
     PSSMUNIT pUnit;
-    int rc = ssmR3Register(pVM, pszName, u32Instance, u32Version, cbGuess, &pUnit);
+    int rc = ssmR3Register(pVM, pszName, u32Instance, u32Version, cbGuess, NULL, &pUnit);
     if (RT_SUCCESS(rc))
     {
@@ -568,5 +595,5 @@
 {
     PSSMUNIT pUnit;
-    int rc = ssmR3Register(pVM, pszName, u32Instance, u32Version, cbGuess, &pUnit);
+    int rc = ssmR3Register(pVM, pszName, u32Instance, u32Version, cbGuess, NULL, &pUnit);
     if (RT_SUCCESS(rc))
     {
@@ -608,5 +635,5 @@
 {
     PSSMUNIT pUnit;
-    int rc = ssmR3Register(pVM, pszName, u32Instance, u32Version, cbGuess, &pUnit);
+    int rc = ssmR3Register(pVM, pszName, u32Instance, u32Version, cbGuess, NULL, &pUnit);
     if (RT_SUCCESS(rc))
     {
Index: /trunk/src/VBox/VMM/testcase/tstSSM.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstSSM.cpp	(revision 20152)
+++ /trunk/src/VBox/VMM/testcase/tstSSM.cpp	(revision 20153)
@@ -651,5 +651,5 @@
      * Register a few callbacks.
      */
-    rc = SSMR3RegisterDevice(pVM, NULL, "SSM Testcase Data Item no.1 (all types)", 1, 0, 256,
+    rc = SSMR3RegisterDevice(pVM, NULL, "SSM Testcase Data Item no.1 (all types)", 1, 0, 256, NULL,
         NULL, Item01Save, NULL,
         NULL, Item01Load, NULL);
@@ -660,5 +660,5 @@
     }
 
-    rc = SSMR3RegisterDevice(pVM, NULL, "SSM Testcase Data Item no.2 (rand mem)", 2, 0, _1M * 8,
+    rc = SSMR3RegisterDevice(pVM, NULL, "SSM Testcase Data Item no.2 (rand mem)", 2, 0, _1M * 8, NULL,
         NULL, Item02Save, NULL,
         NULL, Item02Load, NULL);
@@ -669,5 +669,5 @@
     }
 
-    rc = SSMR3RegisterDevice(pVM, NULL, "SSM Testcase Data Item no.3 (big mem)", 0, 123, 512*_1M,
+    rc = SSMR3RegisterDevice(pVM, NULL, "SSM Testcase Data Item no.3 (big mem)", 0, 123, 512*_1M, NULL,
         NULL, Item03Save, NULL,
         NULL, Item03Load, NULL);
@@ -678,5 +678,5 @@
     }
 
-    rc = SSMR3RegisterDevice(pVM, NULL, "SSM Testcase Data Item no.4 (big zero mem)", 0, 42, 512*_1M,
+    rc = SSMR3RegisterDevice(pVM, NULL, "SSM Testcase Data Item no.4 (big zero mem)", 0, 42, 512*_1M, NULL,
         NULL, Item04Save, NULL,
         NULL, Item04Load, NULL);
