Index: /trunk/src/VBox/VMM/Makefile.kmk
===================================================================
--- /trunk/src/VBox/VMM/Makefile.kmk	(revision 54798)
+++ /trunk/src/VBox/VMM/Makefile.kmk	(revision 54799)
@@ -109,4 +109,7 @@
 ifdef VBOX_WITH_VMM_R0_SWITCH_STACK
  VBoxVMM_DEFS   += VMM_R0_SWITCH_STACK
+endif
+if "$(KBUILD_TYPE)" == "debug" && "$(USERNAME)" == "bird"
+ VBoxVMM_DEFS   += RTMEM_WRAP_TO_EF_APIS
 endif
 VBoxVMM_DEFS.darwin = VMM_R0_SWITCH_STACK
Index: /trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp	(revision 54798)
+++ /trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp	(revision 54799)
@@ -679,4 +679,34 @@
 
 /**
+ * Checks that we've updated the CPUID leaves array correctly.
+ *
+ * This is a no-op in non-strict builds.
+ *
+ * @param   paLeaves            The leaves array.
+ * @param   cLeaves             The number of leaves.
+ */
+static void cpumR3CpuIdAssertOrder(PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves)
+{
+#ifdef VBOX_STRICT
+    for (uint32_t i = 1; i < cLeaves; i++)
+        if (paLeaves[i].uLeaf != paLeaves[i - 1].uLeaf)
+            AssertMsg(paLeaves[i].uLeaf > paLeaves[i - 1].uLeaf, ("%#x vs %#x\n", paLeaves[i].uLeaf, paLeaves[i - 1].uLeaf));
+        else
+        {
+            AssertMsg(paLeaves[i].uSubLeaf > paLeaves[i - 1].uSubLeaf,
+                      ("%#x: %#x vs %#x\n", paLeaves[i].uLeaf, paLeaves[i].uSubLeaf, paLeaves[i - 1].uSubLeaf));
+            AssertMsg(paLeaves[i].fSubLeafMask == paLeaves[i - 1].fSubLeafMask,
+                      ("%#x/%#x: %#x vs %#x\n", paLeaves[i].uLeaf, paLeaves[i].uSubLeaf, paLeaves[i].fSubLeafMask, paLeaves[i - 1].fSubLeafMask));
+            AssertMsg(paLeaves[i].fFlags == paLeaves[i - 1].fFlags,
+                      ("%#x/%#x: %#x vs %#x\n", paLeaves[i].uLeaf, paLeaves[i].uSubLeaf, paLeaves[i].fFlags, paLeaves[i - 1].fFlags));
+        }
+#else
+    NOREF(paLeaves);
+    NOREF(cLeaves);
+#endif
+}
+
+
+/**
  * Inserts a CPU ID leaf, replacing any existing ones.
  *
@@ -782,4 +812,5 @@
 
             paLeaves[i] = *pNewLeaf;
+            cpumR3CpuIdAssertOrder(*ppaLeaves, *pcLeaves);
             return VINF_SUCCESS;
         }
@@ -787,5 +818,6 @@
         /* Find sub-leaf insertion point. */
         while (   i < cLeaves
-               && paLeaves[i].uSubLeaf < pNewLeaf->uSubLeaf)
+               && paLeaves[i].uSubLeaf < pNewLeaf->uSubLeaf
+               && paLeaves[i].uLeaf == pNewLeaf->uLeaf)
             i++;
 
@@ -793,8 +825,10 @@
          * If we've got an exactly matching leaf, replace it.
          */
-        if (   paLeaves[i].uLeaf    == pNewLeaf->uLeaf
+        if (   i < cLeaves
+            && paLeaves[i].uLeaf    == pNewLeaf->uLeaf
             && paLeaves[i].uSubLeaf == pNewLeaf->uSubLeaf)
         {
             paLeaves[i] = *pNewLeaf;
+            cpumR3CpuIdAssertOrder(*ppaLeaves, *pcLeaves);
             return VINF_SUCCESS;
         }
@@ -813,4 +847,6 @@
     *pcLeaves += 1;
     paLeaves[i] = *pNewLeaf;
+
+    cpumR3CpuIdAssertOrder(*ppaLeaves, *pcLeaves);
     return VINF_SUCCESS;
 }
@@ -858,4 +894,6 @@
         *pcLeaves = cLeaves -= (iEnd - iFirst);
     }
+
+    cpumR3CpuIdAssertOrder(paLeaves, *pcLeaves);
 }
 
@@ -1191,4 +1229,5 @@
     }
 
+    cpumR3CpuIdAssertOrder(*ppaLeaves, *pcLeaves);
     return VINF_SUCCESS;
 }
@@ -1859,4 +1898,6 @@
 static int cpumR3CpuIdInstallAndExplodeLeaves(PVM pVM, PCPUM pCpum, PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves)
 {
+    cpumR3CpuIdAssertOrder(paLeaves, cLeaves);
+
     /*
      * Install the CPUID information.
@@ -1866,6 +1907,5 @@
 
     AssertLogRelRCReturn(rc, rc);
-
-
+    pCpum->GuestInfo.cCpuIdLeaves = cLeaves;
     pCpum->GuestInfo.paCpuIdLeavesR0 = MMHyperR3ToR0(pVM, pCpum->GuestInfo.paCpuIdLeavesR3);
     pCpum->GuestInfo.paCpuIdLeavesRC = MMHyperR3ToRC(pVM, pCpum->GuestInfo.paCpuIdLeavesR3);
@@ -3471,5 +3511,13 @@
                     /*
                      * Load the leaves one by one.
+                     *
+                     * The uPrev stuff is a kludge for working around a week worth of bad saved
+                     * states during the CPUID revamp in March 2015.  We saved too many leaves
+                     * due to a bug in cpumR3CpuIdInstallAndExplodeLeaves, thus ending up with
+                     * garbage entires at the end of the array when restoring.  We also had
+                     * a subleaf insertion bug that triggered with the leaf 4 stuff below,
+                     * this kludge doesn't deal correctly with that, but who cares...
                      */
+                    uint32_t uPrev = 0;
                     for (uint32_t i = 0; i < cLeaves && RT_SUCCESS(rc); i++)
                     {
@@ -3477,5 +3525,14 @@
                         rc = SSMR3GetMem(pSSM, &Leaf, sizeof(Leaf));
                         if (RT_SUCCESS(rc))
-                            rc = cpumR3CpuIdInsert(NULL /* pVM */, ppaLeaves, pcLeaves, &Leaf);
+                        {
+                            if (   uVersion != CPUM_SAVED_STATE_VERSION_BAD_CPUID_COUNT
+                                || Leaf.uLeaf >= uPrev)
+                            {
+                                rc = cpumR3CpuIdInsert(NULL /* pVM */, ppaLeaves, pcLeaves, &Leaf);
+                                uPrev = Leaf.uLeaf;
+                            }
+                            else
+                                uPrev = UINT32_MAX;
+                        }
                     }
                 }
Index: /trunk/src/VBox/VMM/include/CPUMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/CPUMInternal.h	(revision 54798)
+++ /trunk/src/VBox/VMM/include/CPUMInternal.h	(revision 54799)
@@ -123,5 +123,8 @@
  * @{ */
 /** The current saved state version. */
-#define CPUM_SAVED_STATE_VERSION                15
+#define CPUM_SAVED_STATE_VERSION                16
+/** CPUID changes with explode forgetting to update the leaf count on
+ * restore, resulting in garbage being saved restoring+saving old states). */
+#define CPUM_SAVED_STATE_VERSION_BAD_CPUID_COUNT 15
 /** The saved state version before the CPUIDs changes. */
 #define CPUM_SAVED_STATE_VERSION_PUT_STRUCT     14
