Index: /trunk/include/VBox/vmm/cpum.h
===================================================================
--- /trunk/include/VBox/vmm/cpum.h	(revision 55228)
+++ /trunk/include/VBox/vmm/cpum.h	(revision 55229)
@@ -68,4 +68,6 @@
     /** The MWait Extensions bits (Std) */
     CPUMCPUIDFEATURE_MWAIT_EXTS,
+    /** The CR4.OSXSAVE bit CPUID mirroring, only use from CPUMSetGuestCR4. */
+    CPUMCPUIDFEATURE_OSXSAVE,
     /** 32bit hackishness. */
     CPUMCPUIDFEATURE_32BIT_HACK = 0x7fffffff
@@ -310,6 +312,8 @@
 /** The leaf contains an APIC ID that needs changing to that of the current CPU. */
 #define CPUMCPUIDLEAF_F_CONTAINS_APIC_ID            RT_BIT_32(1)
+/** The leaf contains an OSXSAVE which needs individual handling on each CPU. */
+#define CPUMCPUIDLEAF_F_CONTAINS_OSXSAVE            RT_BIT_32(2)
 /** Mask of the valid flags. */
-#define CPUMCPUIDLEAF_F_VALID_MASK                  UINT32_C(0x3)
+#define CPUMCPUIDLEAF_F_VALID_MASK                  UINT32_C(0x7)
 /** @} */
 
@@ -889,4 +893,122 @@
 
 
+/**
+ * CPU features and quirks.
+ * This is mostly exploded CPUID info.
+ */
+typedef struct CPUMFEATURES
+{
+    /** The CPU vendor (CPUMCPUVENDOR). */
+    uint8_t         enmCpuVendor;
+    /** The CPU family. */
+    uint8_t         uFamily;
+    /** The CPU model. */
+    uint8_t         uModel;
+    /** The CPU stepping. */
+    uint8_t         uStepping;
+    /** The microarchitecture. */
+#ifndef VBOX_FOR_DTRACE_LIB
+    CPUMMICROARCH   enmMicroarch;
+#else
+    uint32_t        enmMicroarch;
+#endif
+    /** The maximum physical address with of the CPU. */
+    uint8_t         cMaxPhysAddrWidth;
+    /** Alignment padding. */
+    uint8_t         abPadding[1];
+    /** Max size of the extended state (or FPU state if no XSAVE). */
+    uint16_t        cbMaxExtendedState;
+
+    /** Supports MSRs. */
+    uint32_t        fMsr : 1;
+    /** Supports the page size extension (4/2 MB pages). */
+    uint32_t        fPse : 1;
+    /** Supports 36-bit page size extension (4 MB pages can map memory above
+     *  4GB). */
+    uint32_t        fPse36 : 1;
+    /** Supports physical address extension (PAE). */
+    uint32_t        fPae : 1;
+    /** Page attribute table (PAT) support (page level cache control). */
+    uint32_t        fPat : 1;
+    /** Supports the FXSAVE and FXRSTOR instructions. */
+    uint32_t        fFxSaveRstor : 1;
+    /** Supports the XSAVE and XRSTOR instructions. */
+    uint32_t        fXSaveRstor : 1;
+    /** The XSAVE/XRSTOR bit in CR4 has been set (only applicable for host!). */
+    uint32_t        fOpSysXSaveRstor : 1;
+    /** Supports MMX. */
+    uint32_t        fMmx : 1;
+    /** Supports AMD extensions to MMX instructions. */
+    uint32_t        fAmdMmxExts : 1;
+    /** Supports SSE. */
+    uint32_t        fSse : 1;
+    /** Supports SSE2. */
+    uint32_t        fSse2 : 1;
+    /** Supports SSE3. */
+    uint32_t        fSse3 : 1;
+    /** Supports SSSE3. */
+    uint32_t        fSsse3 : 1;
+    /** Supports SSE4.1. */
+    uint32_t        fSse41 : 1;
+    /** Supports SSE4.2. */
+    uint32_t        fSse42 : 1;
+    /** Supports AVX. */
+    uint32_t        fAvx : 1;
+    /** Supports AVX2. */
+    uint32_t        fAvx2 : 1;
+    /** Supports AVX512 foundation. */
+    uint32_t        fAvx512Foundation : 1;
+    /** Supports RDTSC. */
+    uint32_t        fTsc : 1;
+    /** Intel SYSENTER/SYSEXIT support */
+    uint32_t        fSysEnter : 1;
+    /** First generation APIC. */
+    uint32_t        fApic : 1;
+    /** Second generation APIC. */
+    uint32_t        fX2Apic : 1;
+    /** Hypervisor present. */
+    uint32_t        fHypervisorPresent : 1;
+    /** MWAIT & MONITOR instructions supported. */
+    uint32_t        fMonitorMWait : 1;
+    /** MWAIT Extensions present. */
+    uint32_t        fMWaitExtensions : 1;
+
+    /** Supports AMD 3DNow instructions. */
+    uint32_t        f3DNow : 1;
+    /** Supports the 3DNow/AMD64 prefetch instructions (could be nops). */
+    uint32_t        f3DNowPrefetch : 1;
+
+    /** AMD64: Supports long mode. */
+    uint32_t        fLongMode : 1;
+    /** AMD64: SYSCALL/SYSRET support. */
+    uint32_t        fSysCall : 1;
+    /** AMD64: No-execute page table bit. */
+    uint32_t        fNoExecute : 1;
+    /** AMD64: Supports LAHF & SAHF instructions in 64-bit mode. */
+    uint32_t        fLahfSahf : 1;
+    /** AMD64: Supports RDTSCP. */
+    uint32_t        fRdTscP : 1;
+    /** AMD64: Supports MOV CR8 in 32-bit code (lock prefix hack). */
+    uint32_t        fMovCr8In32Bit : 1;
+
+    /** Indicates that FPU instruction and data pointers may leak.
+     * This generally applies to recent AMD CPUs, where the FPU IP and DP pointer
+     * is only saved and restored if an exception is pending. */
+    uint32_t        fLeakyFxSR : 1;
+
+    /** Alignment padding / reserved for future use. */
+    uint32_t        fPadding : 29;
+    uint32_t        auPadding[3];
+} CPUMFEATURES;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(CPUMFEATURES, 32);
+#endif
+/** Pointer to a CPU feature structure. */
+typedef CPUMFEATURES *PCPUMFEATURES;
+/** Pointer to a const CPU feature structure. */
+typedef CPUMFEATURES const *PCCPUMFEATURES;
+
+
+
 /** @name Guest Register Getters.
  * @{ */
Index: /trunk/include/VBox/vmm/cpum.mac
===================================================================
--- /trunk/include/VBox/vmm/cpum.mac	(revision 55228)
+++ /trunk/include/VBox/vmm/cpum.mac	(revision 55229)
@@ -235,5 +235,5 @@
     .msrApicBase        resb    8
     alignb 8
-    .xcr0               resq    1
+    .aXcr               resq    2
     .fXStateMask        resq    1
     .pXStateR0      RTR0PTR_RES 1
Index: /trunk/include/VBox/vmm/cpumctx.h
===================================================================
--- /trunk/include/VBox/vmm/cpumctx.h	(revision 55228)
+++ /trunk/include/VBox/vmm/cpumctx.h	(revision 55229)
@@ -399,6 +399,6 @@
     /** @} */
 
-    /** The XCR0 register. */
-    uint64_t                    xcr0;
+    /** The XCR0..XCR1 registers. */
+    uint64_t                    aXcr[2];
     /** The mask to pass to XSAVE/XRSTOR in EDX:EAX.  If zero we use
      *  FXSAVE/FXRSTOR (since bit 0 will always be set, we only need to test it). */
@@ -415,5 +415,5 @@
 
     /** Size padding. */
-    uint32_t        au32SizePadding[HC_ARCH_BITS == 32 ? 15 : 13];
+    uint32_t        au32SizePadding[HC_ARCH_BITS == 32 ? 13 : 11];
 } CPUMCTX;
 #pragma pack()
Index: /trunk/include/VBox/vmm/vm.h
===================================================================
--- /trunk/include/VBox/vmm/vm.h	(revision 55228)
+++ /trunk/include/VBox/vmm/vm.h	(revision 55229)
@@ -978,4 +978,16 @@
         struct CPUM s;
 #endif
+#ifdef ___VBox_vmm_cpum_h
+        /** Read only info exposed about the host and guest CPUs.   */
+        struct
+        {
+            /** Padding for hidden fields. */
+            uint8_t                 abHidden0[64];
+            /** Host CPU feature information. */
+            CPUMFEATURES            HostFeatures;
+            /** Guest CPU feature information. */
+            CPUMFEATURES            GuestFeatures;
+        } const ro;
+#endif
         uint8_t     padding[1536];      /* multiple of 64 */
     } cpum;
Index: /trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp	(revision 55228)
+++ /trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp	(revision 55229)
@@ -49,4 +49,7 @@
 # pragma optimize("y", off)
 #endif
+
+AssertCompile2MemberOffsets(VM, cpum.s.HostFeatures,  cpum.ro.HostFeatures);
+AssertCompile2MemberOffsets(VM, cpum.s.GuestFeatures, cpum.ro.GuestFeatures);
 
 
@@ -742,7 +745,21 @@
 VMMDECL(int) CPUMSetGuestCR4(PVMCPU pVCpu, uint64_t cr4)
 {
-    if (    (cr4                     & (X86_CR4_PGE | X86_CR4_PAE | X86_CR4_PSE))
-        !=  (pVCpu->cpum.s.Guest.cr4 & (X86_CR4_PGE | X86_CR4_PAE | X86_CR4_PSE)))
+    /*
+     * The CR4.OSXSAVE bit is reflected in CPUID(1).ECX[27].
+     */
+    if (   (cr4                     & X86_CR4_OSXSAVE)
+        != (pVCpu->cpum.s.Guest.cr4 & X86_CR4_OSXSAVE) )
+    {
+        PVM pVM = pVCpu->CTX_SUFF(pVM);
+        if (cr4 & X86_CR4_OSXSAVE)
+            CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_OSXSAVE);
+        else
+            CPUMClearGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_OSXSAVE);
+    }
+
+    if (   (cr4                     & (X86_CR4_PGE | X86_CR4_PAE | X86_CR4_PSE))
+        != (pVCpu->cpum.s.Guest.cr4 & (X86_CR4_PGE | X86_CR4_PAE | X86_CR4_PSE)))
         pVCpu->cpum.s.fChanged |= CPUM_CHANGED_GLOBAL_TLB_FLUSH;
+
     pVCpu->cpum.s.fChanged |= CPUM_CHANGED_CR4;
     pVCpu->cpum.s.Guest.cr4 = cr4;
@@ -1284,12 +1301,16 @@
              * Deal with CPU specific information (currently only APIC ID).
              */
-            if (pLeaf->fFlags & CPUMCPUIDLEAF_F_CONTAINS_APIC_ID)
+            if (pLeaf->fFlags & (CPUMCPUIDLEAF_F_CONTAINS_APIC_ID | CPUMCPUIDLEAF_F_CONTAINS_OSXSAVE))
             {
                 if (uLeaf == 1)
                 {
-                    /* Bits 31-24: Initial APIC ID */
+                    /* EBX: Bits 31-24: Initial APIC ID. */
                     Assert(pVCpu->idCpu <= 255);
                     AssertMsg((pLeaf->uEbx >> 24) == 0, ("%#x\n", pLeaf->uEbx)); /* raw-mode assumption */
                     *pEbx = (pLeaf->uEbx & UINT32_C(0x00ffffff)) | (pVCpu->idCpu << 24);
+
+                    /* ECX: Bit 27: CR4.OSXSAVE mirror. */
+                    *pEcx = (pLeaf->uEcx & ~X86_CPUID_FEATURE_ECX_OSXSAVE)
+                          | (pVCpu->cpum.s.Guest.cr4 & X86_CR4_OSXSAVE ? X86_CPUID_FEATURE_ECX_OSXSAVE : 0);
                 }
                 else if (uLeaf == 0xb)
@@ -1589,4 +1610,21 @@
             break;
 
+        /*
+         * OSXSAVE - only used from CPUMSetGuestCR4.
+         */
+        case CPUMCPUIDFEATURE_OSXSAVE:
+            AssertLogRelReturnVoid(pVM->cpum.s.HostFeatures.fXSaveRstor && pVM->cpum.s.HostFeatures.fOpSysXSaveRstor);
+
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001));
+            AssertLogRelReturnVoid(pLeaf);
+
+            /* UNI: Special case for single CPU to make life simple for CPUMPatchHlpCpuId. */
+            if (pVM->cCpus == 1)
+                pVM->cpum.s.aGuestCpuIdPatmStd[1].uEcx = pLeaf->uEcx |= X86_CPUID_FEATURE_ECX_OSXSAVE;
+            /* SMP: Set flag indicating OSXSAVE updating (superfluous because of the APIC ID, but that's fine). */
+            else
+                ASMAtomicOrU32(&pLeaf->fFlags, CPUMCPUIDLEAF_F_CONTAINS_OSXSAVE);
+            break;
+
         default:
             AssertMsgFailed(("enmFeature=%d\n", enmFeature));
@@ -1626,4 +1664,5 @@
         case CPUMCPUIDFEATURE_MWAIT_EXTS:   return pVM->cpum.s.GuestFeatures.fMWaitExtensions;
 
+        case CPUMCPUIDFEATURE_OSXSAVE:
         case CPUMCPUIDFEATURE_INVALID:
         case CPUMCPUIDFEATURE_32BIT_HACK:
@@ -1732,4 +1771,20 @@
             Log(("CPUM: ClearGuestCpuIdFeature: Disabled MWAIT Extensions!\n"));
             break;
+
+        /*
+         * OSXSAVE - only used from CPUMSetGuestCR4.
+         */
+        case CPUMCPUIDFEATURE_OSXSAVE:
+            AssertLogRelReturnVoid(pVM->cpum.s.HostFeatures.fXSaveRstor && pVM->cpum.s.HostFeatures.fOpSysXSaveRstor);
+
+            pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001));
+            AssertLogRelReturnVoid(pLeaf);
+
+            /* UNI: Special case for single CPU to make life easy for CPUMPatchHlpCpuId. */
+            if (pVM->cCpus == 1)
+                pVM->cpum.s.aGuestCpuIdPatmStd[1].uEcx = pLeaf->uEcx &= ~X86_CPUID_FEATURE_ECX_OSXSAVE;
+            /* else: SMP: We never set the OSXSAVE bit and leaving the CONTAINS_OSXSAVE flag is fine. */
+            break;
+
 
         default:
Index: /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 55228)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 55229)
@@ -296,37 +296,16 @@
 
 /**
- * Tests if an AMD CPUID feature (extended) is marked present - ECX.
- */
-#define IEM_IS_AMD_CPUID_FEATURE_PRESENT_ECX(a_fEcx)    iemRegIsAmdCpuIdFeaturePresent(pIemCpu, 0, (a_fEcx))
-
-/**
- * Tests if an AMD CPUID feature (extended) is marked present - EDX.
- */
-#define IEM_IS_AMD_CPUID_FEATURE_PRESENT_EDX(a_fEdx)    iemRegIsAmdCpuIdFeaturePresent(pIemCpu, (a_fEdx), 0)
-
-/**
- * Tests if at least on of the specified AMD CPUID features (extended) are
- * marked present.
- */
-#define IEM_IS_AMD_CPUID_FEATURES_ANY_PRESENT(a_fEdx, a_fEcx)   iemRegIsAmdCpuIdFeaturePresent(pIemCpu, (a_fEdx), (a_fEcx))
-
-/**
- * Checks if an Intel CPUID feature is present.
- */
-#define IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(a_fEdx)  \
-    (   ((a_fEdx) & (X86_CPUID_FEATURE_EDX_TSC | 0)) \
-     || iemRegIsIntelCpuIdFeaturePresent(pIemCpu, (a_fEdx), 0) )
-
-/**
- * Checks if an Intel CPUID feature is present.
- */
-#define IEM_IS_INTEL_CPUID_FEATURE_PRESENT_ECX(a_fEcx)  \
-    ( iemRegIsIntelCpuIdFeaturePresent(pIemCpu, 0, (a_fEcx)) )
-
-/**
- * Checks if an Intel CPUID feature is present in the host CPU.
- */
-#define IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX_ON_HOST(a_fEdx)  \
-    ( (a_fEdx) & pIemCpu->fHostCpuIdStdFeaturesEdx )
+ * Returns a (const) pointer to the CPUMFEATURES for the guest CPU.
+ * @returns PCCPUMFEATURES
+ * @param   a_pIemCpu       The IEM state of the current CPU.
+ */
+#define IEM_GET_GUEST_CPU_FEATURES(a_pIemCpu) (&(IEMCPU_TO_VM(a_pIemCpu)->cpum.ro.GuestFeatures))
+
+/**
+ * Returns a (const) pointer to the CPUMFEATURES for the host CPU.
+ * @returns PCCPUMFEATURES
+ * @param   a_pIemCpu       The IEM state of the current CPU.
+ */
+#define IEM_GET_HOST_CPU_FEATURES(a_pIemCpu)  (&(IEMCPU_TO_VM(a_pIemCpu)->cpum.ro.HostFeatures))
 
 /**
@@ -5110,44 +5089,4 @@
 }
 
-
-/**
- * Checks if an Intel CPUID feature bit is set.
- *
- * @returns true / false.
- *
- * @param   pIemCpu             The IEM per CPU data.
- * @param   fEdx                The EDX bit to test, or 0 if ECX.
- * @param   fEcx                The ECX bit to test, or 0 if EDX.
- * @remarks Used via IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX,
- *          IEM_IS_INTEL_CPUID_FEATURE_PRESENT_ECX and others.
- */
-static bool iemRegIsIntelCpuIdFeaturePresent(PIEMCPU pIemCpu, uint32_t fEdx, uint32_t fEcx)
-{
-    uint32_t uEax, uEbx, uEcx, uEdx;
-    CPUMGetGuestCpuId(IEMCPU_TO_VMCPU(pIemCpu), 0x00000001, 0, &uEax, &uEbx, &uEcx, &uEdx);
-    return (fEcx && (uEcx & fEcx))
-        || (fEdx && (uEdx & fEdx));
-}
-
-
-/**
- * Checks if an AMD CPUID feature bit is set.
- *
- * @returns true / false.
- *
- * @param   pIemCpu             The IEM per CPU data.
- * @param   fEdx                The EDX bit to test, or 0 if ECX.
- * @param   fEcx                The ECX bit to test, or 0 if EDX.
- * @remarks Used via IEM_IS_AMD_CPUID_FEATURE_PRESENT_EDX,
- *          IEM_IS_AMD_CPUID_FEATURE_PRESENT_ECX and others.
- */
-static bool iemRegIsAmdCpuIdFeaturePresent(PIEMCPU pIemCpu, uint32_t fEdx, uint32_t fEcx)
-{
-    uint32_t uEax, uEbx, uEcx, uEdx;
-    CPUMGetGuestCpuId(IEMCPU_TO_VMCPU(pIemCpu), 0x80000001, 0, &uEax, &uEbx, &uEcx, &uEdx);
-    return (fEcx && (uEcx & fEcx))
-        || (fEdx && (uEdx & fEdx));
-}
-
 /** @}  */
 
@@ -8318,5 +8257,5 @@
         if (   (pIemCpu->CTX_SUFF(pCtx)->cr0 & X86_CR0_EM) \
             || !(pIemCpu->CTX_SUFF(pCtx)->cr4 & X86_CR4_OSFXSR) \
-            || !IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_FEATURE_EDX_SSE2) ) \
+            || !IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fSse2) \
             return iemRaiseUndefinedOpcode(pIemCpu); \
         if (pIemCpu->CTX_SUFF(pCtx)->cr0 & X86_CR0_TS) \
@@ -8326,5 +8265,5 @@
     do { \
         if (   ((pIemCpu)->CTX_SUFF(pCtx)->cr0 & X86_CR0_EM) \
-            || !IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_FEATURE_EDX_MMX) ) \
+            || !IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fMmx) \
             return iemRaiseUndefinedOpcode(pIemCpu); \
         if (pIemCpu->CTX_SUFF(pCtx)->cr0 & X86_CR0_TS) \
@@ -8334,6 +8273,6 @@
     do { \
         if (   ((pIemCpu)->CTX_SUFF(pCtx)->cr0 & X86_CR0_EM) \
-            || (   !IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_FEATURE_EDX_SSE) \
-                && !IEM_IS_AMD_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_AMD_FEATURE_EDX_AXMMX) ) ) \
+            || (   !IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fSse \
+                && !IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fAmdMmxExts) ) \
             return iemRaiseUndefinedOpcode(pIemCpu); \
         if (pIemCpu->CTX_SUFF(pCtx)->cr0 & X86_CR0_TS) \
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 55228)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 55229)
@@ -4981,6 +4981,6 @@
             //if (xxx)
             //    fValid |= X86_CR4_VMXE;
-            //if (xxx)
-            //    fValid |= X86_CR4_OSXSAVE;
+            if (IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fXSaveRstor)
+                fValid |= X86_CR4_OSXSAVE;
             if (uNewCrX & ~(uint64_t)fValid)
             {
@@ -5335,5 +5335,5 @@
      * Check preconditions.
      */
-    if (!IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_FEATURE_EDX_TSC))
+    if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fTsc)
         return iemRaiseUndefinedOpcode(pIemCpu);
 
@@ -5370,5 +5370,5 @@
      * Check preconditions.
      */
-    if (!IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_FEATURE_EDX_MSR))
+    if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fMsr)
         return iemRaiseUndefinedOpcode(pIemCpu);
     if (pIemCpu->uCpl != 0)
@@ -5419,5 +5419,5 @@
      * Check preconditions.
      */
-    if (!IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_FEATURE_EDX_MSR))
+    if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fMsr)
         return iemRaiseUndefinedOpcode(pIemCpu);
     if (pIemCpu->uCpl != 0)
@@ -5725,5 +5725,5 @@
         return iemRaiseUndefinedOpcode(pIemCpu); /** @todo MSR[0xC0010015].MonMwaitUserEn if we care. */
     }
-    if (!IEM_IS_INTEL_CPUID_FEATURE_PRESENT_ECX(X86_CPUID_FEATURE_ECX_MONITOR))
+    if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fMonitorMWait)
     {
         Log2(("monitor: Not in CPUID\n"));
@@ -5781,5 +5781,5 @@
         return iemRaiseUndefinedOpcode(pIemCpu);
     }
-    if (!IEM_IS_INTEL_CPUID_FEATURE_PRESENT_ECX(X86_CPUID_FEATURE_ECX_MONITOR))
+    if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fMonitorMWait)
     {
         Log2(("mwait: Not in CPUID\n"));
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h	(revision 55228)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h	(revision 55229)
@@ -1308,6 +1308,5 @@
 {
     /* AMD prefetch group, Intel implements this as NOP Ev (and so do we). */
-    if (!IEM_IS_AMD_CPUID_FEATURES_ANY_PRESENT(X86_CPUID_EXT_FEATURE_EDX_LONG_MODE | X86_CPUID_AMD_FEATURE_EDX_3DNOW,
-                                               X86_CPUID_AMD_FEATURE_ECX_3DNOWPRF))
+    if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->f3DNowPrefetch)
     {
         IEMOP_MNEMONIC("GrpP");
@@ -1426,5 +1425,5 @@
 FNIEMOP_DEF(iemOp_3Dnow)
 {
-    if (!IEM_IS_AMD_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_AMD_FEATURE_EDX_3DNOW))
+    if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->f3DNow)
     {
         IEMOP_MNEMONIC("3Dnow");
@@ -1556,5 +1555,5 @@
     {
         /* The lock prefix can be used to encode CR8 accesses on some CPUs. */
-        if (!IEM_IS_AMD_CPUID_FEATURE_PRESENT_ECX(X86_CPUID_AMD_FEATURE_ECX_CR8L))
+        if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fMovCr8In32Bit)
             return IEMOP_RAISE_INVALID_OPCODE(); /* #UD takes precedence over #GP(), see test. */
         iCrReg |= 8;
@@ -1602,5 +1601,5 @@
     {
         /* The lock prefix can be used to encode CR8 accesses on some CPUs. */
-        if (!IEM_IS_AMD_CPUID_FEATURE_PRESENT_ECX(X86_CPUID_AMD_FEATURE_ECX_CR8L))
+        if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fMovCr8In32Bit)
             return IEMOP_RAISE_INVALID_OPCODE(); /* #UD takes precedence over #GP(), see test. */
         iCrReg |= 8;
@@ -4924,5 +4923,5 @@
 {
     IEMOP_MNEMONIC("fxsave m512");
-    if (!IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_FEATURE_EDX_FXSR))
+    if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fFxSaveRstor)
         return IEMOP_RAISE_INVALID_OPCODE();
 
@@ -4944,5 +4943,5 @@
 {
     IEMOP_MNEMONIC("fxrstor m512");
-    if (!IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_FEATURE_EDX_FXSR))
+    if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fFxSaveRstor)
         return IEMOP_RAISE_INVALID_OPCODE();
 
@@ -4984,9 +4983,9 @@
     IEMOP_MNEMONIC("lfence");
     IEMOP_HLP_NO_LOCK_PREFIX();
-    if (!IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_FEATURE_EDX_SSE2))
+    if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fSse2)
         return IEMOP_RAISE_INVALID_OPCODE();
 
     IEM_MC_BEGIN(0, 0);
-    if (IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX_ON_HOST(X86_CPUID_FEATURE_EDX_SSE2))
+    if (IEM_GET_HOST_CPU_FEATURES(pIemCpu)->fSse2)
         IEM_MC_CALL_VOID_AIMPL_0(iemAImpl_lfence);
     else
@@ -5003,9 +5002,9 @@
     IEMOP_MNEMONIC("mfence");
     IEMOP_HLP_NO_LOCK_PREFIX();
-    if (!IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_FEATURE_EDX_SSE2))
+    if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fSse2)
         return IEMOP_RAISE_INVALID_OPCODE();
 
     IEM_MC_BEGIN(0, 0);
-    if (IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX_ON_HOST(X86_CPUID_FEATURE_EDX_SSE2))
+    if (IEM_GET_HOST_CPU_FEATURES(pIemCpu)->fSse2)
         IEM_MC_CALL_VOID_AIMPL_0(iemAImpl_mfence);
     else
@@ -5022,9 +5021,9 @@
     IEMOP_MNEMONIC("sfence");
     IEMOP_HLP_NO_LOCK_PREFIX();
-    if (!IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(X86_CPUID_FEATURE_EDX_SSE2))
+    if (!IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fSse2)
         return IEMOP_RAISE_INVALID_OPCODE();
 
     IEM_MC_BEGIN(0, 0);
-    if (IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX_ON_HOST(X86_CPUID_FEATURE_EDX_SSE2))
+    if (IEM_GET_HOST_CPU_FEATURES(pIemCpu)->fSse2)
         IEM_MC_CALL_VOID_AIMPL_0(iemAImpl_sfence);
     else
@@ -10551,5 +10550,5 @@
     IEMOP_HLP_NO_LOCK_PREFIX();
     if (   pIemCpu->enmCpuMode == IEMMODE_64BIT
-        && !IEM_IS_AMD_CPUID_FEATURE_PRESENT_ECX(X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF))
+        && !IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fLahfSahf)
         return IEMOP_RAISE_INVALID_OPCODE();
     IEM_MC_BEGIN(0, 2);
@@ -10575,5 +10574,5 @@
     IEMOP_HLP_NO_LOCK_PREFIX();
     if (   pIemCpu->enmCpuMode == IEMMODE_64BIT
-        && !IEM_IS_AMD_CPUID_FEATURE_PRESENT_ECX(X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF))
+        && !IEM_GET_GUEST_CPU_FEATURES(pIemCpu)->fLahfSahf)
         return IEMOP_RAISE_INVALID_OPCODE();
     IEM_MC_BEGIN(0, 1);
Index: /trunk/src/VBox/VMM/VMMR3/CPUM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/CPUM.cpp	(revision 55228)
+++ /trunk/src/VBox/VMM/VMMR3/CPUM.cpp	(revision 55229)
@@ -917,4 +917,11 @@
     pFpuCtx->MXCSR_MASK             = 0xffff; /** @todo REM always changed this for us. Should probably check if the HW really
                                                         supports all bits, since a zero value here should be read as 0xffbf. */
+    pCtx->aXcr[0]                   = XSAVE_C_X87;
+    if (pVM->cpum.s.HostFeatures.cbMaxExtendedState >= RT_OFFSETOF(X86XSAVEAREA, Hdr))
+    {
+        /* The entire FXSAVE state needs loading when we switch to XSAVE/XRSTOR
+           as we don't know what happened before.  (Bother optimize later?) */
+        pCtx->pXStateR3->Hdr.bmXState = XSAVE_C_X87 | XSAVE_C_SSE;
+    }
 
     /*
Index: /trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp	(revision 55228)
+++ /trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp	(revision 55229)
@@ -1603,4 +1603,9 @@
             pFeatures->fLahfSahf        = RT_BOOL(pExtLeaf->uEcx & X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF);
             pFeatures->fRdTscP          = RT_BOOL(pExtLeaf->uEdx & X86_CPUID_EXT_FEATURE_EDX_RDTSCP);
+            pFeatures->fMovCr8In32Bit   = RT_BOOL(pExtLeaf->uEcx & X86_CPUID_AMD_FEATURE_ECX_CMPL);
+            pFeatures->f3DNow           = RT_BOOL(pExtLeaf->uEdx & X86_CPUID_AMD_FEATURE_EDX_3DNOW);
+            pFeatures->f3DNowPrefetch   = (pExtLeaf->uEcx & X86_CPUID_AMD_FEATURE_ECX_3DNOWPRF)
+                                       || (pExtLeaf->uEdx & (  X86_CPUID_EXT_FEATURE_EDX_LONG_MODE
+                                                             | X86_CPUID_AMD_FEATURE_EDX_3DNOW));
         }
 
@@ -1618,4 +1623,5 @@
             pFeatures->fMmx            |= RT_BOOL(pExtLeaf->uEdx & X86_CPUID_AMD_FEATURE_EDX_MMX);
             pFeatures->fTsc            |= RT_BOOL(pExtLeaf->uEdx & X86_CPUID_AMD_FEATURE_EDX_TSC);
+            pFeatures->fAmdMmxExts      = RT_BOOL(pExtLeaf->uEdx & X86_CPUID_AMD_FEATURE_EDX_AXMMX);
         }
 
@@ -2106,4 +2112,7 @@
     CPUMISAEXTCFG   enmSse41;
     CPUMISAEXTCFG   enmSse42;
+    CPUMISAEXTCFG   enmAvx;
+    CPUMISAEXTCFG   enmAvx2;
+    CPUMISAEXTCFG   enmXSave;
     CPUMISAEXTCFG   enmAesNi;
     CPUMISAEXTCFG   enmPClMul;
@@ -2441,7 +2450,7 @@
                            //| X86_CPUID_FEATURE_ECX_TSCDEADL - not implemented yet.
                            | (pConfig->enmAesNi ? X86_CPUID_FEATURE_ECX_AES : 0)
-                           //| X86_CPUID_FEATURE_ECX_XSAVE - not implemented yet.
-                           //| X86_CPUID_FEATURE_ECX_OSXSAVE - mirrors CR4.OSXSAVE state
-                           //| X86_CPUID_FEATURE_ECX_AVX   - not implemented yet.
+                           | (pConfig->enmXSave ? X86_CPUID_FEATURE_ECX_XSAVE : 0 )
+                           //| X86_CPUID_FEATURE_ECX_OSXSAVE - mirrors CR4.OSXSAVE state, set dynamically.
+                           | (pConfig->enmAvx ? X86_CPUID_FEATURE_ECX_AVX : 0)
                            //| X86_CPUID_FEATURE_ECX_F16C  - not implemented yet.
                            | (pConfig->enmRdRand ? X86_CPUID_FEATURE_ECX_RDRAND : 0)
@@ -2460,6 +2469,6 @@
         PORTABLE_DISABLE_FEATURE_BIT_CFG(1, pStdFeatureLeaf->uEcx, POPCNT, X86_CPUID_FEATURE_ECX_POPCNT, pConfig->enmPopCnt);
         PORTABLE_DISABLE_FEATURE_BIT(    1, pStdFeatureLeaf->uEcx, F16C,   X86_CPUID_FEATURE_ECX_F16C);
-        PORTABLE_DISABLE_FEATURE_BIT(    1, pStdFeatureLeaf->uEcx, XSAVE,  X86_CPUID_FEATURE_ECX_XSAVE);
-        PORTABLE_DISABLE_FEATURE_BIT(    1, pStdFeatureLeaf->uEcx, AVX,    X86_CPUID_FEATURE_ECX_AVX);
+        PORTABLE_DISABLE_FEATURE_BIT_CFG(1, pStdFeatureLeaf->uEcx, XSAVE,  X86_CPUID_FEATURE_ECX_XSAVE,  pConfig->enmXSave);
+        PORTABLE_DISABLE_FEATURE_BIT_CFG(1, pStdFeatureLeaf->uEcx, AVX,    X86_CPUID_FEATURE_ECX_AVX,    pConfig->enmAvx);
         PORTABLE_DISABLE_FEATURE_BIT_CFG(1, pStdFeatureLeaf->uEcx, RDRAND, X86_CPUID_FEATURE_ECX_RDRAND, pConfig->enmRdRand);
         PORTABLE_DISABLE_FEATURE_BIT_CFG(1, pStdFeatureLeaf->uEcx, CX16,   X86_CPUID_FEATURE_ECX_CX16,   pConfig->enmCmpXchg16b);
@@ -2489,7 +2498,5 @@
                                           | X86_CPUID_FEATURE_ECX_PDCM
                                           | X86_CPUID_FEATURE_ECX_DCA
-                                          | X86_CPUID_FEATURE_ECX_XSAVE
                                           | X86_CPUID_FEATURE_ECX_OSXSAVE
-                                          | X86_CPUID_FEATURE_ECX_AVX
                                           )));
     }
@@ -2524,4 +2531,8 @@
     if (pConfig->enmAesNi == CPUMISAEXTCFG_ENABLED_ALWAYS)
         pStdFeatureLeaf->uEcx |= X86_CPUID_FEATURE_ECX_AES;
+    if (pConfig->enmXSave == CPUMISAEXTCFG_ENABLED_ALWAYS)
+        pStdFeatureLeaf->uEcx |= X86_CPUID_FEATURE_ECX_XSAVE;
+    if (pConfig->enmAvx == CPUMISAEXTCFG_ENABLED_ALWAYS)
+        pStdFeatureLeaf->uEcx |= X86_CPUID_FEATURE_ECX_AVX;
     if (pConfig->enmRdRand == CPUMISAEXTCFG_ENABLED_ALWAYS)
         pStdFeatureLeaf->uEcx |= X86_CPUID_FEATURE_ECX_RDRAND;
@@ -2818,5 +2829,5 @@
                                //| X86_CPUID_STEXT_FEATURE_EBX_BMI1              RT_BIT(3)
                                //| X86_CPUID_STEXT_FEATURE_EBX_HLE               RT_BIT(4)
-                               //| X86_CPUID_STEXT_FEATURE_EBX_AVX2              RT_BIT(5)
+                               | (pConfig->enmAvx2 ? X86_CPUID_STEXT_FEATURE_EBX_AVX2 : 0)
                                //| RT_BIT(6) - reserved
                                //| X86_CPUID_STEXT_FEATURE_EBX_SMEP              RT_BIT(7)
@@ -2854,5 +2865,5 @@
                 {
                     PORTABLE_DISABLE_FEATURE_BIT(    1, pCurLeaf->uEbx, FSGSBASE,   X86_CPUID_STEXT_FEATURE_EBX_FSGSBASE);
-                    PORTABLE_DISABLE_FEATURE_BIT(    1, pCurLeaf->uEbx, AVX2,       X86_CPUID_STEXT_FEATURE_EBX_AVX2);
+                    PORTABLE_DISABLE_FEATURE_BIT_CFG(1, pCurLeaf->uEbx, AVX2,       X86_CPUID_STEXT_FEATURE_EBX_AVX2, pConfig->enmAvx2);
                     PORTABLE_DISABLE_FEATURE_BIT(    1, pCurLeaf->uEbx, SMEP,       X86_CPUID_STEXT_FEATURE_EBX_SMEP);
                     PORTABLE_DISABLE_FEATURE_BIT(    1, pCurLeaf->uEbx, BMI2,       X86_CPUID_STEXT_FEATURE_EBX_BMI2);
@@ -2870,4 +2881,6 @@
 
                 /* Force standard feature bits. */
+                if (pConfig->enmAvx2 == CPUMISAEXTCFG_ENABLED_ALWAYS)
+                    pCurLeaf->uEbx |= X86_CPUID_STEXT_FEATURE_EBX_AVX2;
                 if (pConfig->enmRdSeed == CPUMISAEXTCFG_ENABLED_ALWAYS)
                     pCurLeaf->uEbx |= X86_CPUID_STEXT_FEATURE_EBX_RDSEED;
@@ -2987,12 +3000,57 @@
      * Clear them all as we don't currently implement extended CPU state.
      */
-    uSubLeaf = 0;
-    while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 13, uSubLeaf)) != NULL)
-    {
-        pCurLeaf->uEax = 0;
-        pCurLeaf->uEbx = 0;
-        pCurLeaf->uEcx = 0;
-        pCurLeaf->uEdx = 0;
-        uSubLeaf++;
+    /* Figure out the supported XCR0/XSS mask component. */
+    uint64_t fGuestXcr0Mask = 0;
+    pStdFeatureLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 1, 0);
+    if (pStdFeatureLeaf && (pStdFeatureLeaf->uEcx & X86_CPUID_FEATURE_ECX_XSAVE))
+    {
+        fGuestXcr0Mask = XSAVE_C_X87 | XSAVE_C_SSE;
+        if (pStdFeatureLeaf && (pStdFeatureLeaf->uEcx & X86_CPUID_FEATURE_ECX_AVX))
+            fGuestXcr0Mask |= XSAVE_C_YMM;
+        pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 7, 0);
+        if (pCurLeaf && (pCurLeaf->uEbx & X86_CPUID_STEXT_FEATURE_EBX_AVX512F))
+            fGuestXcr0Mask |= XSAVE_C_ZMM_16HI | XSAVE_C_ZMM_HI256 | XSAVE_C_OPMASK;
+        fGuestXcr0Mask &= pCpum->fXStateHostMask;
+    }
+    pStdFeatureLeaf = NULL;
+    pCpum->fXStateGuestMask = fGuestXcr0Mask;
+
+    /* Work the sub-leaves. */
+    for (uSubLeaf = 0; uSubLeaf < 63; uSubLeaf++)
+    {
+        pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 13, uSubLeaf);
+        if (pCurLeaf)
+        {
+            if (fGuestXcr0Mask)
+            {
+                switch (uSubLeaf)
+                {
+                    case 0:
+                        pCurLeaf->uEax &= RT_LO_U32(fGuestXcr0Mask);
+                        pCurLeaf->uEdx &= RT_HI_U32(fGuestXcr0Mask);
+                        continue;
+                    case 1:
+                        pCurLeaf->uEax &= 0;
+                        pCurLeaf->uEcx &= 0;
+                        pCurLeaf->uEdx &= 0;
+                        continue;
+                    default:
+                        if (fGuestXcr0Mask & RT_BIT_64(uSubLeaf))
+                        {
+                            AssertLogRel(!(pCurLeaf->uEcx & 1));
+                            pCurLeaf->uEcx = 0; /* Bit 0 should be zero (XCR0), the reset are reserved... */
+                            pCurLeaf->uEdx = 0; /* it's reserved... */
+                            continue;
+                        }
+                        break;
+                }
+            }
+
+            /* Clear the leaf. */
+            pCurLeaf->uEax = 0;
+            pCurLeaf->uEbx = 0;
+            pCurLeaf->uEcx = 0;
+            pCurLeaf->uEdx = 0;
+        }
     }
 
@@ -3384,4 +3442,34 @@
 
 /**
+ * Reads a value in /CPUM/IsaExts/ node, forcing it to DISABLED if wanted.
+ *
+ * @returns VBox status code (error message raised).
+ * @param   pVM             The VM handle (for errors).
+ * @param   pIsaExts        The /CPUM/IsaExts node (can be NULL).
+ * @param   pszValueName    The value / extension name.
+ * @param   penmValue       Where to return the choice.
+ * @param   enmDefault      The default choice.
+ * @param   fAllowed        Allowed choice.  Applied both to the result and to
+ *                          the default value.
+ */
+static int cpumR3CpuIdReadIsaExtCfgEx(PVM pVM, PCFGMNODE pIsaExts, const char *pszValueName,
+                                      CPUMISAEXTCFG *penmValue, CPUMISAEXTCFG enmDefault, bool fAllowed)
+{
+    Assert(fAllowed == true || fAllowed == false);
+    int rc;
+    if (fAllowed)
+        rc = cpumR3CpuIdReadIsaExtCfg(pVM, pIsaExts, pszValueName, penmValue, enmDefault);
+    else
+    {
+        rc = cpumR3CpuIdReadIsaExtCfg(pVM, pIsaExts, pszValueName, penmValue, false /*enmDefault*/);
+        if (RT_SUCCESS(rc) && *penmValue == CPUMISAEXTCFG_ENABLED_ALWAYS)
+            LogRel(("CPUM: Ignoring forced '%s'\n", pszValueName));
+        *penmValue = CPUMISAEXTCFG_DISABLED;
+    }
+    return rc;
+}
+
+
+/**
  * Reads a value in /CPUM/IsaExts/ node that used to be located in /CPUM/.
  *
@@ -3554,4 +3642,40 @@
      */
     rc = cpumR3CpuIdReadIsaExtCfgLegacy(pVM, pIsaExts, pCpumCfg, "SSE4.2", &pConfig->enmSse42, true);
+    AssertLogRelRCReturn(rc, rc);
+
+#if 0 /* Incomplete, so not yet enabled.  */
+    bool const fMayHaveXSave = fNestedPagingAndFullGuestExec
+                            && pVM->cpum.s.HostFeatures.fXSaveRstor
+                            && pVM->cpum.s.HostFeatures.fOpSysXSaveRstor
+                            && pVM->cpum.s.HostFeatures.enmCpuVendor == CPUMCPUVENDOR_INTEL /** @todo test and enable on AMD! */;
+#else
+    bool const fMayHaveXSave = false;
+#endif
+    /** @cfgm{/CPUM/IsaExts/XSAVE, boolean, depends}
+     * Expose XSAVE/XRSTOR to the guest if available.  For the time being the
+     * default is to only expose this to VMs with nested paging and AMD-V or
+     * unrestricted guest execution mode.  Not possible to force this one without
+     * host support at the moment.
+     */
+    rc = cpumR3CpuIdReadIsaExtCfgEx(pVM, pIsaExts, "XSAVE", &pConfig->enmXSave, fNestedPagingAndFullGuestExec,
+                                    fMayHaveXSave /*fAllowed*/);
+    AssertLogRelRCReturn(rc, rc);
+
+    /** @cfgm{/CPUM/IsaExts/AVX, boolean, depends}
+     * Expose the AVX instruction set extensions to the guest if available and
+     * XSAVE is exposed too.  For the time being the default is to only expose this
+     * to VMs with nested paging and AMD-V or unrestricted guest execution mode.
+     */
+    rc = cpumR3CpuIdReadIsaExtCfgEx(pVM, pIsaExts, "AVX", &pConfig->enmAvx, fNestedPagingAndFullGuestExec,
+                                    fMayHaveXSave && pConfig->enmXSave /*fAllowed*/);
+    AssertLogRelRCReturn(rc, rc);
+
+    /** @cfgm{/CPUM/IsaExts/AVX2, boolean, depends}
+     * Expose the AVX2 instruction set extensions to the guest if available and
+     * XSAVE is exposed too. For the time being the default is to only expose this
+     * to VMs with nested paging and AMD-V or unrestricted guest execution mode.
+     */
+    rc = cpumR3CpuIdReadIsaExtCfgEx(pVM, pIsaExts, "AVX2", &pConfig->enmAvx2, fNestedPagingAndFullGuestExec,
+                                    fMayHaveXSave && pConfig->enmXSave /*fAllowed*/);
     AssertLogRelRCReturn(rc, rc);
 
@@ -4527,5 +4651,5 @@
     CPUID_GST_FEATURE_RET(Std, uEcx, X86_CPUID_FEATURE_ECX_AES);     // -> EMU
     CPUID_GST_FEATURE_RET(Std, uEcx, X86_CPUID_FEATURE_ECX_XSAVE);   // -> EMU
-    CPUID_GST_FEATURE_RET(Std, uEcx, X86_CPUID_FEATURE_ECX_OSXSAVE); // -> EMU
+    CPUID_GST_FEATURE_IGN(Std, uEcx, X86_CPUID_FEATURE_ECX_OSXSAVE);
     CPUID_GST_FEATURE_RET(Std, uEcx, X86_CPUID_FEATURE_ECX_AVX);     // -> EMU?
     CPUID_GST_FEATURE_RET(Std, uEcx, X86_CPUID_FEATURE_ECX_F16C);
@@ -4647,5 +4771,71 @@
     /** @todo check leaf 7   */
 
-    /** @todo XSAVE: Stricter XSAVE feature checks for all modes. */
+    /* CPUID(d) - XCR0 stuff - takes ECX as input.
+     * ECX=0:   EAX - Valid bits in XCR0[31:0].
+     *          EBX - Maximum state size as per current XCR0 value.
+     *          ECX - Maximum state size for all supported features.
+     *          EDX - Valid bits in XCR0[63:32].
+     * ECX=1:   EAX - Various X-features.
+     *          EBX - Maximum state size as per current XCR0|IA32_XSS value.
+     *          ECX - Valid bits in IA32_XSS[31:0].
+     *          EDX - Valid bits in IA32_XSS[63:32].
+     * ECX=N, where N in 2..63 and indicates a bit in XCR0 and/or IA32_XSS,
+     *        if the bit invalid all four registers are set to zero.
+     *          EAX - The state size for this feature.
+     *          EBX - The state byte offset of this feature.
+     *          ECX - Bit 0 indicates whether this sub-leaf maps to a valid IA32_XSS bit (=1) or a valid XCR0 bit (=0).
+     *          EDX - Reserved, but is set to zero if invalid sub-leaf index.
+     */
+    PCPUMCPUIDLEAF pCurLeaf = cpumR3CpuIdGetLeaf(paLeaves, cLeaves, UINT32_C(0x0000000d), 0);
+    if (   pCurLeaf
+        && (aGuestCpuIdStd[1].uEcx & X86_CPUID_FEATURE_ECX_XSAVE)
+        && (   pCurLeaf->uEax
+            || pCurLeaf->uEbx
+            || pCurLeaf->uEcx
+            || pCurLeaf->uEdx) )
+    {
+        uint64_t fGuestXcr0Mask = RT_MAKE_U64(pCurLeaf->uEax, pCurLeaf->uEdx);
+        if (fGuestXcr0Mask & ~pVM->cpum.s.fXStateHostMask)
+            return SSMR3SetLoadError(pSSM, VERR_SSM_LOAD_CPUID_MISMATCH, RT_SRC_POS,
+                                     N_("CPUID(0xd/0).EDX:EAX mismatch: %#llx saved, %#llx supported by the current host (XCR0 bits)"),
+                                     fGuestXcr0Mask, pVM->cpum.s.fXStateHostMask);
+
+        /* We don't support any additional features yet. */
+        pCurLeaf = cpumR3CpuIdGetLeaf(paLeaves, cLeaves, UINT32_C(0x0000000d), 1);
+        if (pCurLeaf && pCurLeaf->uEax)
+            return SSMR3SetLoadError(pSSM, VERR_SSM_LOAD_CPUID_MISMATCH, RT_SRC_POS,
+                                     N_("CPUID(0xd/1).EAX=%#x, expected zero"), pCurLeaf->uEax);
+        if (pCurLeaf && (pCurLeaf->uEcx || pCurLeaf->uEdx))
+            return SSMR3SetLoadError(pSSM, VERR_SSM_LOAD_CPUID_MISMATCH, RT_SRC_POS,
+                                     N_("CPUID(0xd/1).EDX:ECX=%#llx, expected zero"),
+                                     RT_MAKE_U64(pCurLeaf->uEdx, pCurLeaf->uEcx));
+
+
+        if (pVM->cpum.s.fXStateGuestMask != fGuestXcr0Mask)
+        {
+            LogRel(("CPUM: fXStateGuestMask=%#lx -> %#llx\n", pVM->cpum.s.fXStateGuestMask, fGuestXcr0Mask));
+            pVM->cpum.s.fXStateGuestMask = fGuestXcr0Mask;
+        }
+
+        for (uint32_t uSubLeaf = 2; uSubLeaf < 64; uSubLeaf++)
+        {
+            pCurLeaf = cpumR3CpuIdGetLeaf(paLeaves, cLeaves, UINT32_C(0x0000000d), uSubLeaf);
+            if (pCurLeaf)
+            {
+                /* If advertised, the state component offset and size must match the one used by host. */
+                if (pCurLeaf->uEax || pCurLeaf->uEbx || pCurLeaf->uEcx || pCurLeaf->uEdx)
+                {
+                    CPUMCPUID RawHost;
+                    ASMCpuIdExSlow(UINT32_C(0x0000000d), 0, uSubLeaf, 0,
+                                   &RawHost.uEax, &RawHost.uEbx, &RawHost.uEcx, &RawHost.uEdx);
+                    if (   RawHost.uEbx != pCurLeaf->uEbx
+                        || RawHost.uEax != pCurLeaf->uEax)
+                        return SSMR3SetLoadError(pSSM, VERR_SSM_LOAD_CPUID_MISMATCH, RT_SRC_POS,
+                                                 N_("CPUID(0xd/%#x).EBX/EAX=%#x/%#x, current host uses %#x/%#x (offset/size)"),
+                                                 uSubLeaf, pCurLeaf->uEbx, pCurLeaf->uEax, RawHost.uEbx, RawHost.uEax);
+                }
+            }
+        }
+    }
 
 #undef CPUID_CHECK_RET
Index: /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp	(revision 55228)
+++ /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp	(revision 55229)
@@ -71,19 +71,10 @@
         if (idCpu == 0)
         {
-            uint32_t uIgnored;
-            CPUMGetGuestCpuId(pVCpu, 1, 0, &uIgnored, &uIgnored,
-                              &pVCpu->iem.s.fCpuIdStdFeaturesEcx, &pVCpu->iem.s.fCpuIdStdFeaturesEdx);
             pVCpu->iem.s.enmCpuVendor             = CPUMGetGuestCpuVendor(pVM);
-
-            ASMCpuId_ECX_EDX(1, &pVCpu->iem.s.fHostCpuIdStdFeaturesEcx, &pVCpu->iem.s.fHostCpuIdStdFeaturesEdx);
             pVCpu->iem.s.enmHostCpuVendor         = CPUMGetHostCpuVendor(pVM);
         }
         else
         {
-            pVCpu->iem.s.fCpuIdStdFeaturesEcx     = pVM->aCpus[0].iem.s.fCpuIdStdFeaturesEcx;
-            pVCpu->iem.s.fCpuIdStdFeaturesEdx     = pVM->aCpus[0].iem.s.fCpuIdStdFeaturesEdx;
             pVCpu->iem.s.enmCpuVendor             = pVM->aCpus[0].iem.s.enmCpuVendor;
-            pVCpu->iem.s.fHostCpuIdStdFeaturesEcx = pVM->aCpus[0].iem.s.fHostCpuIdStdFeaturesEcx;
-            pVCpu->iem.s.fHostCpuIdStdFeaturesEdx = pVM->aCpus[0].iem.s.fHostCpuIdStdFeaturesEdx;
             pVCpu->iem.s.enmHostCpuVendor         = pVM->aCpus[0].iem.s.enmHostCpuVendor;
         }
Index: /trunk/src/VBox/VMM/include/CPUMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/CPUMInternal.h	(revision 55228)
+++ /trunk/src/VBox/VMM/include/CPUMInternal.h	(revision 55229)
@@ -148,113 +148,4 @@
 
 
-
-/**
- * CPU features and quirks.
- * This is mostly exploded CPUID info.
- */
-typedef struct CPUMFEATURES
-{
-    /** The CPU vendor (CPUMCPUVENDOR). */
-    uint8_t         enmCpuVendor;
-    /** The CPU family. */
-    uint8_t         uFamily;
-    /** The CPU model. */
-    uint8_t         uModel;
-    /** The CPU stepping. */
-    uint8_t         uStepping;
-    /** The microarchitecture. */
-#ifndef VBOX_FOR_DTRACE_LIB
-    CPUMMICROARCH   enmMicroarch;
-#else
-    uint32_t        enmMicroarch;
-#endif
-    /** The maximum physical address with of the CPU. */
-    uint8_t         cMaxPhysAddrWidth;
-    /** Alignment padding. */
-    uint8_t         abPadding[1];
-    /** Max size of the extended state (or FPU state if no XSAVE). */
-    uint16_t        cbMaxExtendedState;
-
-    /** Supports MSRs. */
-    uint32_t        fMsr : 1;
-    /** Supports the page size extension (4/2 MB pages). */
-    uint32_t        fPse : 1;
-    /** Supports 36-bit page size extension (4 MB pages can map memory above
-     *  4GB). */
-    uint32_t        fPse36 : 1;
-    /** Supports physical address extension (PAE). */
-    uint32_t        fPae : 1;
-    /** Page attribute table (PAT) support (page level cache control). */
-    uint32_t        fPat : 1;
-    /** Supports the FXSAVE and FXRSTOR instructions. */
-    uint32_t        fFxSaveRstor : 1;
-    /** Supports the XSAVE and XRSTOR instructions. */
-    uint32_t        fXSaveRstor : 1;
-    /** The XSAVE/XRSTOR bit in CR4 has been set (only applicable for host!). */
-    uint32_t        fOpSysXSaveRstor : 1;
-    /** Supports MMX. */
-    uint32_t        fMmx : 1;
-    /** Supports SSE. */
-    uint32_t        fSse : 1;
-    /** Supports SSE2. */
-    uint32_t        fSse2 : 1;
-    /** Supports SSE3. */
-    uint32_t        fSse3 : 1;
-    /** Supports SSSE3. */
-    uint32_t        fSsse3 : 1;
-    /** Supports SSE4.1. */
-    uint32_t        fSse41 : 1;
-    /** Supports SSE4.2. */
-    uint32_t        fSse42 : 1;
-    /** Supports AVX. */
-    uint32_t        fAvx : 1;
-    /** Supports AVX2. */
-    uint32_t        fAvx2 : 1;
-    /** Supports AVX512 foundation. */
-    uint32_t        fAvx512Foundation : 1;
-    /** Supports RDTSC. */
-    uint32_t        fTsc : 1;
-    /** Intel SYSENTER/SYSEXIT support */
-    uint32_t        fSysEnter : 1;
-    /** First generation APIC. */
-    uint32_t        fApic : 1;
-    /** Second generation APIC. */
-    uint32_t        fX2Apic : 1;
-    /** Hypervisor present. */
-    uint32_t        fHypervisorPresent : 1;
-    /** MWAIT & MONITOR instructions supported. */
-    uint32_t        fMonitorMWait : 1;
-    /** MWAIT Extensions present. */
-    uint32_t        fMWaitExtensions : 1;
-
-    /** AMD64: Supports long mode. */
-    uint32_t        fLongMode : 1;
-    /** AMD64: SYSCALL/SYSRET support. */
-    uint32_t        fSysCall : 1;
-    /** AMD64: No-execute page table bit. */
-    uint32_t        fNoExecute : 1;
-    /** AMD64: Supports LAHF & SAHF instructions in 64-bit mode. */
-    uint32_t        fLahfSahf : 1;
-    /** AMD64: Supports RDTSCP. */
-    uint32_t        fRdTscP : 1;
-
-    /** Indicates that FPU instruction and data pointers may leak.
-     * This generally applies to recent AMD CPUs, where the FPU IP and DP pointer
-     * is only saved and restored if an exception is pending. */
-    uint32_t        fLeakyFxSR : 1;
-
-    /** Alignment padding / reserved for future use. */
-    uint32_t        fPadding : 1;
-    uint64_t        auPadding[2];
-} CPUMFEATURES;
-#ifndef VBOX_FOR_DTRACE_LIB
-AssertCompileSize(CPUMFEATURES, 32);
-#endif
-/** Pointer to a CPU feature structure. */
-typedef CPUMFEATURES *PCPUMFEATURES;
-/** Pointer to a const CPU feature structure. */
-typedef CPUMFEATURES const *PCCPUMFEATURES;
-
-
 /**
  * CPU info
@@ -509,5 +400,22 @@
      * This is used to verify load order dependencies (PGM). */
     bool                    fPendingRestore;
-    uint8_t                 abPadding[HC_ARCH_BITS == 64 ? 6 : 2];
+    uint8_t                 abPadding0[6];
+
+    /** XSAVE/XRTOR components we can expose to the guest mask. */
+    uint64_t                fXStateGuestMask;
+    /** XSAVE/XRSTOR host mask.  Only state components in this mask can be exposed
+     * to the guest.  This is 0 if no XSAVE/XRSTOR bits can be exposed. */
+    uint64_t                fXStateHostMask;
+    uint8_t                 abPadding1[24];
+
+    /** Host CPU feature information.
+     * Externaly visible via the VM structure, aligned on 64-byte boundrary. */
+    CPUMFEATURES            HostFeatures;
+    /** Guest CPU feature information.
+     * Externaly visible via that VM structure, aligned with HostFeatures. */
+    CPUMFEATURES            GuestFeatures;
+    /** Guest CPU info. */
+    CPUMINFO                GuestInfo;
+
 
     /** The standard set of CpuId leaves. */
@@ -517,18 +425,4 @@
     /** The centaur set of CpuId leaves. */
     CPUMCPUID               aGuestCpuIdPatmCentaur[4];
-
-#if HC_ARCH_BITS == 32
-    uint8_t                 abPadding2[4];
-#endif
-
-    /** Guest CPU info. */
-    CPUMINFO                GuestInfo;
-    /** Guest CPU feature information. */
-    CPUMFEATURES            GuestFeatures;
-    /** Host CPU feature information. */
-    CPUMFEATURES            HostFeatures;
-    /** XSAVE/XRSTOR host mask.  Only state components in this mask can be exposed
-     * to the guest.  This is 0 if no XSAVE/XRSTOR bits can be exposed. */
-    uint64_t                fXStateHostMask;
 
     /** @name MSR statistics.
@@ -543,4 +437,6 @@
     /** @} */
 } CPUM;
+AssertCompileMemberOffset(CPUM, HostFeatures, 64);
+AssertCompileMemberOffset(CPUM, GuestFeatures, 96);
 /** Pointer to the CPUM instance data residing in the shared VM structure. */
 typedef CPUM *PCPUM;
Index: /trunk/src/VBox/VMM/include/CPUMInternal.mac
===================================================================
--- /trunk/src/VBox/VMM/include/CPUMInternal.mac	(revision 55228)
+++ /trunk/src/VBox/VMM/include/CPUMInternal.mac	(revision 55229)
@@ -76,18 +76,22 @@
 struc CPUM
     ;...
-    .offCPUMCPU0          resd    1
-    .fHostUseFlags        resd    1
+    .offCPUMCPU0                resd    1
+    .fHostUseFlags              resd    1
 
     ; CR4 masks
-    .CR4.AndMask          resd    1
-    .CR4.OrMask           resd    1
+    .CR4.AndMask                resd    1
+    .CR4.OrMask                 resd    1
     ; entered rawmode?
-    .u8PortableCpuIdLevel resb    1
-    .fPendingRestore      resb    1
-%if RTHCPTR_CB == 8
-    .abPadding            resb    6
-%else
-    .abPadding            resb    2
-%endif
+    .u8PortableCpuIdLevel       resb    1
+    .fPendingRestore            resb    1
+
+    alignb 8
+    .fXStateGuestMask           resq    1
+    .fXStateHostMask            resq    1
+
+    alignb 64
+    .HostFeatures               resb    32
+    .GuestFeatures              resb    32
+    .GuestInfo                  resb    RTHCPTR_CB*4 + RTRCPTR_CB*2 + 4*12
 
     ; Patch manager saved state compatability CPUID leaf arrays
@@ -96,20 +100,12 @@
     .aGuestCpuIdPatmCentaur     resb    16*4
 
-%if HC_ARCH_BITS == 32
-    .abPadding2           resb    4
-%endif
-
-    .GuestInfo            resb    RTHCPTR_CB*4 + RTRCPTR_CB*2 + 4*12
-    .GuestFeatures        resb    32
-    .HostFeatures         resb    32
-    .fXStateHostMask      resq    1
-
-    .cMsrWrites                 resq  1
-    .cMsrWritesToIgnoredBits    resq  1
-    .cMsrWritesRaiseGp          resq  1
-    .cMsrWritesUnknown          resq  1
-    .cMsrReads                  resq  1
-    .cMsrReadsRaiseGp           resq  1
-    .cMsrReadsUnknown           resq  1
+    alignb 8
+    .cMsrWrites                 resq    1
+    .cMsrWritesToIgnoredBits    resq    1
+    .cMsrWritesRaiseGp          resq    1
+    .cMsrWritesUnknown          resq    1
+    .cMsrReads                  resq    1
+    .cMsrReadsRaiseGp           resq    1
+    .cMsrReadsUnknown           resq    1
 endstruc
 
@@ -218,5 +214,5 @@
     .Guest.msrKERNELGSBASE    resb    8
     .Guest.msrApicBase        resb    8
-    .Guest.xcr0               resq    1
+    .Guest.aXcr               resq    2
     .Guest.fXStateMask        resq    1
     .Guest.pXStateR0      RTR0PTR_RES 1
@@ -477,5 +473,5 @@
     .Hyper.msrKERNELGSBASE    resb    8
     .Hyper.msrApicBase        resb    8
-    .Hyper.xcr0               resq    1
+    .Hyper.aXcr               resq    2
     .Hyper.fXStateMask        resq    1
     .Hyper.pXStateR0      RTR0PTR_RES 1
Index: /trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 55228)
+++ /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 55229)
@@ -373,10 +373,4 @@
     /** @name Target CPU information.
      * @{ */
-    /** EDX value of CPUID(1).
-     * @remarks Some bits are subject to change and must be queried dynamically. */
-    uint32_t                fCpuIdStdFeaturesEdx;
-    /** ECX value of CPUID(1).
-     * @remarks Some bits are subject to change and must be queried dynamically. */
-    uint32_t                fCpuIdStdFeaturesEcx;
     /** The CPU vendor. */
     CPUMCPUVENDOR           enmCpuVendor;
@@ -385,8 +379,4 @@
     /** @name Host CPU information.
      * @{ */
-    /** EDX value of CPUID(1). */
-    uint32_t                fHostCpuIdStdFeaturesEdx;
-    /** ECX value of CPUID(1). */
-    uint32_t                fHostCpuIdStdFeaturesEcx;
     /** The CPU vendor. */
     CPUMCPUVENDOR           enmHostCpuVendor;
Index: /trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp	(revision 55228)
+++ /trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp	(revision 55229)
@@ -138,12 +138,8 @@
 #define IEM_IS_LONG_MODE(a_pIemCpu)                         (g_fRandom)
 #define IEM_IS_REAL_MODE(a_pIemCpu)                         (g_fRandom)
-#define IEM_IS_AMD_CPUID_FEATURE_PRESENT_ECX(a_fEcx)        (g_fRandom)
-#define IEM_IS_AMD_CPUID_FEATURE_PRESENT_EDX(a_fEdx)        (g_fRandom)
-#define IEM_IS_AMD_CPUID_FEATURES_ANY_PRESENT(a_fEdx, a_fEcx) (g_fRandom)
-#define IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX(a_fEdx)      (g_fRandom)
-#define IEM_IS_INTEL_CPUID_FEATURE_PRESENT_ECX(a_fEcx)      (g_fRandom)
-#define IEM_IS_INTEL_CPUID_FEATURE_PRESENT_EDX_ON_HOST(a_fEdx) (g_fRandom)
 #define IEM_IS_GUEST_CPU_AMD(a_pIemCpu)                     (g_fRandom)
 #define IEM_IS_GUEST_CPU_INTEL(a_pIemCpu)                   (g_fRandom)
+#define IEM_GET_GUEST_CPU_FEATURES(a_pIemCpu)               ((PCCPUMFEATURES)(uintptr_t)42)
+#define IEM_GET_HOST_CPU_FEATURES(a_pIemCpu)                ((PCCPUMFEATURES)(uintptr_t)88)
 
 #define iemRecalEffOpSize(a_pIemCpu)                        do { } while (0)
