Index: trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp	(revision 57055)
+++ trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp	(revision 57056)
@@ -524,5 +524,5 @@
  * @param   cLeaves             The number of leaves in the array.
  * @param   uLeaf               The leaf to locate.
- * @param   uSubLeaf            The subleaf to locate.  Pass 0 if no subleaves.
+ * @param   uSubLeaf            The subleaf to locate.  Pass 0 if no sub-leaves.
  */
 static PCPUMCPUIDLEAF cpumR3CpuIdGetLeaf(PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, uint32_t uLeaf, uint32_t uSubLeaf)
@@ -545,5 +545,5 @@
  * @param   cLeaves             The number of leaves in the array.
  * @param   uLeaf               The leaf to locate.
- * @param   uSubLeaf            The subleaf to locate.  Pass 0 if no subleaves.
+ * @param   uSubLeaf            The subleaf to locate.  Pass 0 if no sub-leaves.
  * @param   pLegacy             The legacy output leaf.
  */
@@ -715,5 +715,5 @@
  * Inserts a CPU ID leaf, replacing any existing ones.
  *
- * When inserting a simple leaf where we already got a series of subleaves with
+ * When inserting a simple leaf where we already got a series of sub-leaves with
  * the same leaf number (eax), the simple leaf will replace the whole series.
  *
@@ -1038,5 +1038,5 @@
  * @param   pLeaf       Where to store the found leaf.
  * @param   uLeaf       The leaf to locate.
- * @param   uSubLeaf    The subleaf to locate.  Pass 0 if no subleaves.
+ * @param   uSubLeaf    The subleaf to locate.  Pass 0 if no sub-leaves.
  */
 VMMR3DECL(int) CPUMR3CpuIdGetLeaf(PVM pVM, PCPUMCPUIDLEAF pLeaf, uint32_t uLeaf, uint32_t uSubLeaf)
@@ -1174,5 +1174,5 @@
                            relevant details in the release log. */
                         LogRel(("CPUM: VERR_CPUM_TOO_MANY_CPUID_SUBLEAVES! uLeaf=%#x cSubLeaves=%#x\n", uLeaf, cSubLeaves));
-                        LogRel(("------------------ dump of problematic subleaves ------------------\n"));
+                        LogRel(("------------------ dump of problematic sub-leaves -----------------\n"));
                         for (uint32_t uSubLeaf = 0; uSubLeaf < 128; uSubLeaf++)
                         {
@@ -2402,4 +2402,57 @@
 
 /**
+ * Used by cpumR3CpuIdSanitize to ensure that we don't have any sub-leaves for
+ * the given leaf.
+ *
+ * @returns pLeaf.
+ * @param   pCpum       The CPUM instance data.
+ * @param   pLeaf       The leaf to ensure is alone with it's EAX input value.
+ */
+static PCPUMCPUIDLEAF cpumR3CpuIdMakeSingleLeaf(PCPUM pCpum, PCPUMCPUIDLEAF pLeaf)
+{
+    Assert((uintptr_t)(pLeaf - pCpum->GuestInfo.paCpuIdLeavesR3) < pCpum->GuestInfo.cCpuIdLeaves);
+    if (pLeaf->fSubLeafMask != 0)
+    {
+        /*
+         * Figure out how many sub-leaves in need of removal (we'll keep the first).
+         * Log everything while we're at it.
+         */
+        LogRel(("CPUM:\n"
+                "CPUM: Unexpected CPUID sub-leaves for leaf %#x; fSubLeafMask=%#x\n", pLeaf->uLeaf, pLeaf->fSubLeafMask));
+        PCPUMCPUIDLEAF  pLast    = &pCpum->GuestInfo.paCpuIdLeavesR3[pCpum->GuestInfo.cCpuIdLeaves - 1];
+        PCPUMCPUIDLEAF  pSubLeaf = pLeaf;
+        for (;;)
+        {
+            LogRel(("CPUM: %08x/%08x: %08x %08x %08x %08x; flags=%#x mask=%#x\n",
+                    pSubLeaf->uLeaf, pSubLeaf->uSubLeaf,
+                    pSubLeaf->uEax, pSubLeaf->uEbx, pSubLeaf->uEcx, pSubLeaf->uEdx,
+                    pSubLeaf->fFlags, pSubLeaf->fSubLeafMask));
+            if (pSubLeaf == pLast || pSubLeaf[1].uLeaf != pLeaf->uLeaf)
+                break;
+            pSubLeaf++;
+        }
+        LogRel(("CPUM:\n"));
+
+        /*
+         * Remove the offending sub-leaves.
+         */
+        if (pSubLeaf != pLeaf)
+        {
+            if (pSubLeaf != pLast)
+                memmove(pLeaf + 1, pSubLeaf + 1, (uintptr_t)pLast - (uintptr_t)pSubLeaf);
+            pCpum->GuestInfo.cCpuIdLeaves -= (uint32_t)(pSubLeaf - pLeaf);
+        }
+
+        /*
+         * Convert the first sub-leaf into a single leaf.
+         */
+        pLeaf->uSubLeaf     = 0;
+        pLeaf->fSubLeafMask = 0;
+    }
+    return pLeaf;
+}
+
+
+/**
  * Sanitizes and adjust the CPUID leaves.
  *
@@ -2451,5 +2504,5 @@
     PCPUMCPUIDLEAF pStdFeatureLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 1, 0); /* Note! Must refetch when used later. */
     AssertLogRelReturn(pStdFeatureLeaf, VERR_CPUM_IPE_2);
-    AssertLogRelReturn(pStdFeatureLeaf->fSubLeafMask == 0, VERR_CPUM_IPE_2);
+    pStdFeatureLeaf = cpumR3CpuIdMakeSingleLeaf(pCpum, pStdFeatureLeaf);
 
     pStdFeatureLeaf->uEdx &= X86_CPUID_FEATURE_EDX_FPU
@@ -2623,5 +2676,5 @@
     if (pExtFeatureLeaf)
     {
-        AssertLogRelReturn(pExtFeatureLeaf->fSubLeafMask == 0, VERR_CPUM_IPE_2);
+        pExtFeatureLeaf = cpumR3CpuIdMakeSingleLeaf(pCpum, pExtFeatureLeaf);
 
         pExtFeatureLeaf->uEdx &= X86_CPUID_AMD_FEATURE_EDX_FPU
@@ -2759,6 +2812,5 @@
      * AMD:   Reserved
      * VIA:   Reserved
-     * Safe to expose.  Restrict the number of calls to 1 since we don't
-     * implement this kind of subleaves (is there hardware that does??).
+     * Safe to expose.
      */
     uint32_t        uSubLeaf = 0;
