Index: trunk/include/VBox/vmm/hm_svm.h
===================================================================
--- trunk/include/VBox/vmm/hm_svm.h	(revision 76395)
+++ trunk/include/VBox/vmm/hm_svm.h	(revision 76397)
@@ -28,5 +28,4 @@
 
 #include <VBox/types.h>
-#include <VBox/err.h>
 #include <iprt/assert.h>
 #include <iprt/asm.h>
Index: trunk/include/VBox/vmm/hm_vmx.h
===================================================================
--- trunk/include/VBox/vmm/hm_vmx.h	(revision 76395)
+++ trunk/include/VBox/vmm/hm_vmx.h	(revision 76397)
@@ -28,7 +28,6 @@
 
 #include <VBox/types.h>
-#include <VBox/err.h>
 #include <iprt/x86.h>
-#include <iprt/assert.h>
+#include <iprt/assertcompile.h>
 
 /* In Visual C++ versions prior to 2012, the vmx intrinsics are only available
@@ -4064,173 +4063,5 @@
 
 
-/** @defgroup grp_hm_vmx_inline    VMX Inline Helpers
- * @{
- */
-/**
- * Gets the effective width of a VMCS field given it's encoding adjusted for
- * HIGH/FULL access for 64-bit fields.
- *
- * @returns The effective VMCS field width.
- * @param   uFieldEnc   The VMCS field encoding.
- *
- * @remarks Warning! This function does not verify the encoding is for a valid and
- *          supported VMCS field.
- */
-DECLINLINE(uint8_t) HMVmxGetVmcsFieldWidthEff(uint32_t uFieldEnc)
-{
-    /* Only the "HIGH" parts of all 64-bit fields have bit 0 set. */
-    if (uFieldEnc & RT_BIT(0))
-        return VMXVMCSFIELDWIDTH_32BIT;
-
-    /* Bits 13:14 contains the width of the VMCS field, see VMXVMCSFIELDWIDTH_XXX. */
-    return (uFieldEnc >> 13) & 0x3;
-}
-
-/**
- * Returns whether the given VMCS field is a read-only VMCS field or not.
- *
- * @returns @c true if it's a read-only field, @c false otherwise.
- * @param   uFieldEnc   The VMCS field encoding.
- *
- * @remarks Warning! This function does not verify the encoding is for a valid and
- *          supported VMCS field.
- */
-DECLINLINE(bool) HMVmxIsVmcsFieldReadOnly(uint32_t uFieldEnc)
-{
-    /* See Intel spec. B.4.2 "Natural-Width Read-Only Data Fields". */
-    return (RT_BF_GET(uFieldEnc, VMX_BF_VMCS_ENC_TYPE) == VMXVMCSFIELDTYPE_VMEXIT_INFO);
-}
-
-/**
- * Returns whether the given VM-entry interruption-information type is valid or not.
- *
- * @returns @c true if it's a valid type, @c false otherwise.
- * @param   fSupportsMTF    Whether the Monitor-Trap Flag CPU feature is supported.
- * @param   uType           The VM-entry interruption-information type.
- */
-DECLINLINE(bool) HMVmxIsEntryIntInfoTypeValid(bool fSupportsMTF, uint8_t uType)
-{
-    /* See Intel spec. 26.2.1.3 "VM-Entry Control Fields". */
-    switch (uType)
-    {
-        case VMX_ENTRY_INT_INFO_TYPE_EXT_INT:
-        case VMX_ENTRY_INT_INFO_TYPE_NMI:
-        case VMX_ENTRY_INT_INFO_TYPE_HW_XCPT:
-        case VMX_ENTRY_INT_INFO_TYPE_SW_INT:
-        case VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT:
-        case VMX_ENTRY_INT_INFO_TYPE_SW_XCPT:           return true;
-        case VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT:       return fSupportsMTF;
-        default:
-            return false;
-    }
-}
-
-/**
- * Returns whether the given VM-entry interruption-information vector and type
- * combination is valid or not.
- *
- * @returns @c true if it's a valid vector/type combination, @c false otherwise.
- * @param   uVector     The VM-entry interruption-information vector.
- * @param   uType       The VM-entry interruption-information type.
- *
- * @remarks Warning! This function does not validate the type field individually.
- *          Use it after verifying type is valid using HMVmxIsEntryIntInfoTypeValid.
- */
-DECLINLINE(bool) HMVmxIsEntryIntInfoVectorValid(uint8_t uVector, uint8_t uType)
-{
-    /* See Intel spec. 26.2.1.3 "VM-Entry Control Fields". */
-    if (   uType == VMX_ENTRY_INT_INFO_TYPE_NMI
-        && uVector != X86_XCPT_NMI)
-        return false;
-    if (   uType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
-        && uVector > X86_XCPT_LAST)
-        return false;
-    if (   uType == VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT
-        && uVector != VMX_ENTRY_INT_INFO_VECTOR_MTF)
-        return false;
-    return true;
-}
-
-
-/**
- * Returns whether or not the VM-exit is trap-like or fault-like.
- *
- * @returns @c true if it's a trap-like VM-exit, @c false otherwise.
- * @param   uExitReason     The VM-exit reason.
- *
- * @remarks Warning! This does not validate the VM-exit reason.
- */
-DECLINLINE(bool) HMVmxIsVmexitTrapLike(uint32_t uExitReason)
-{
-    /*
-     * Trap-like VM-exits - The instruction causing the VM-exit completes before the
-     * VM-exit occurs.
-     *
-     * Fault-like VM-exits - The instruction causing the VM-exit is not completed before
-     * the VM-exit occurs.
-     *
-     * See Intel spec. 25.5.2 "Monitor Trap Flag".
-     * See Intel spec. 29.1.4 "EOI Virtualization".
-     * See Intel spec. 29.4.3.3 "APIC-Write VM Exits".
-     * See Intel spec. 29.1.2 "TPR Virtualization".
-     */
-    /** @todo NSTVMX: r=ramshankar: What about VM-exits due to debug traps (single-step,
-     *        I/O breakpoints, data breakpoints), debug exceptions (data breakpoint)
-     *        delayed by MovSS blocking, machine-check exceptions. */
-    switch (uExitReason)
-    {
-        case VMX_EXIT_MTF:
-        case VMX_EXIT_VIRTUALIZED_EOI:
-        case VMX_EXIT_APIC_WRITE:
-        case VMX_EXIT_TPR_BELOW_THRESHOLD:
-            return true;
-    }
-    return false;
-}
-
-
-/**
- * Returns whether the VM-entry is vectoring or not given the VM-entry interruption
- * information field.
- *
- * @returns @c true if the VM-entry is vectoring, @c false otherwise.
- * @param   uEntryIntInfo       The VM-entry interruption information field.
- * @param   pEntryIntInfoType   The VM-entry interruption information type field.
- *                              Optional, can be NULL. Only updated when this
- *                              function returns @c true.
- */
-DECLINLINE(bool) HMVmxIsVmentryVectoring(uint32_t uEntryIntInfo, uint8_t *pEntryIntInfoType)
-{
-    /*
-     * The definition of what is a vectoring VM-entry is taken
-     * from Intel spec. 26.6 "Special Features of VM Entry".
-     */
-    if (!VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo))
-        return false;
-
-    /* Scope and keep variable defines on top to satisy archaic c89 nonsense. */
-    {
-        uint8_t const uType = VMX_ENTRY_INT_INFO_TYPE(uEntryIntInfo);
-        switch (uType)
-        {
-            case VMX_ENTRY_INT_INFO_TYPE_EXT_INT:
-            case VMX_ENTRY_INT_INFO_TYPE_NMI:
-            case VMX_ENTRY_INT_INFO_TYPE_HW_XCPT:
-            case VMX_ENTRY_INT_INFO_TYPE_SW_INT:
-            case VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT:
-            case VMX_ENTRY_INT_INFO_TYPE_SW_XCPT:
-            {
-                if (pEntryIntInfoType)
-                    *pEntryIntInfoType = uType;
-                return true;
-            }
-        }
-    }
-    return false;
-}
-/** @} */
-
-
-/** @defgroup grp_hm_vmx_c    VMX Assembly Helpers
+/** @defgroup grp_hm_vmx_c    VMX C Helpers
  *
  * These are functions that strictly only implement VT-x functionality that is in
@@ -4247,523 +4078,6 @@
 
 
-/** @defgroup grp_hm_vmx_asm    VMX Assembly Helpers
- * @{
- */
-
-/**
- * Restores some host-state fields that need not be done on every VM-exit.
- *
- * @returns VBox status code.
- * @param   fRestoreHostFlags   Flags of which host registers needs to be
- *                              restored.
- * @param   pRestoreHost        Pointer to the host-restore structure.
- */
-DECLASM(int) VMXRestoreHostState(uint32_t fRestoreHostFlags, PVMXRESTOREHOST pRestoreHost);
-
-
-/**
- * Dispatches an NMI to the host.
- */
-DECLASM(int) VMXDispatchHostNmi(void);
-
-
-/**
- * Executes VMXON.
- *
- * @returns VBox status code.
- * @param   HCPhysVmxOn      Physical address of VMXON structure.
- */
-#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS)
-DECLASM(int) VMXEnable(RTHCPHYS HCPhysVmxOn);
-#else
-DECLINLINE(int) VMXEnable(RTHCPHYS HCPhysVmxOn)
-{
-# if RT_INLINE_ASM_GNU_STYLE
-    int rc = VINF_SUCCESS;
-    __asm__ __volatile__ (
-       "push     %3                                             \n\t"
-       "push     %2                                             \n\t"
-       ".byte    0xf3, 0x0f, 0xc7, 0x34, 0x24  # VMXON [esp]    \n\t"
-       "ja       2f                                             \n\t"
-       "je       1f                                             \n\t"
-       "movl     $" RT_XSTR(VERR_VMX_INVALID_VMXON_PTR)", %0    \n\t"
-       "jmp      2f                                             \n\t"
-       "1:                                                      \n\t"
-       "movl     $" RT_XSTR(VERR_VMX_VMXON_FAILED)", %0         \n\t"
-       "2:                                                      \n\t"
-       "add      $8, %%esp                                      \n\t"
-       :"=rm"(rc)
-       :"0"(VINF_SUCCESS),
-        "ir"((uint32_t)HCPhysVmxOn),        /* don't allow direct memory reference here, */
-        "ir"((uint32_t)(HCPhysVmxOn >> 32)) /* this would not work with -fomit-frame-pointer */
-       :"memory"
-       );
-    return rc;
-
-# elif VMX_USE_MSC_INTRINSICS
-    unsigned char rcMsc = __vmx_on(&HCPhysVmxOn);
-    if (RT_LIKELY(rcMsc == 0))
-        return VINF_SUCCESS;
-    return rcMsc == 2 ? VERR_VMX_INVALID_VMXON_PTR : VERR_VMX_VMXON_FAILED;
-
-# else
-    int rc = VINF_SUCCESS;
-    __asm
-    {
-        push    dword ptr [HCPhysVmxOn + 4]
-        push    dword ptr [HCPhysVmxOn]
-        _emit   0xf3
-        _emit   0x0f
-        _emit   0xc7
-        _emit   0x34
-        _emit   0x24     /* VMXON [esp] */
-        jnc     vmxon_good
-        mov     dword ptr [rc], VERR_VMX_INVALID_VMXON_PTR
-        jmp     the_end
-
-vmxon_good:
-        jnz     the_end
-        mov     dword ptr [rc], VERR_VMX_VMXON_FAILED
-the_end:
-        add     esp, 8
-    }
-    return rc;
-# endif
-}
+/** @} */
+
 #endif
 
-
-/**
- * Executes VMXOFF.
- */
-#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS)
-DECLASM(void) VMXDisable(void);
-#else
-DECLINLINE(void) VMXDisable(void)
-{
-# if RT_INLINE_ASM_GNU_STYLE
-    __asm__ __volatile__ (
-       ".byte 0x0f, 0x01, 0xc4  # VMXOFF                        \n\t"
-       );
-
-# elif VMX_USE_MSC_INTRINSICS
-    __vmx_off();
-
-# else
-    __asm
-    {
-        _emit   0x0f
-        _emit   0x01
-        _emit   0xc4   /* VMXOFF */
-    }
-# endif
-}
-#endif
-
-
-/**
- * Executes VMCLEAR.
- *
- * @returns VBox status code.
- * @param   HCPhysVmcs       Physical address of VM control structure.
- */
-#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS)
-DECLASM(int) VMXClearVmcs(RTHCPHYS HCPhysVmcs);
-#else
-DECLINLINE(int) VMXClearVmcs(RTHCPHYS HCPhysVmcs)
-{
-# if RT_INLINE_ASM_GNU_STYLE
-    int rc = VINF_SUCCESS;
-    __asm__ __volatile__ (
-       "push    %3                                              \n\t"
-       "push    %2                                              \n\t"
-       ".byte   0x66, 0x0f, 0xc7, 0x34, 0x24  # VMCLEAR [esp]   \n\t"
-       "jnc     1f                                              \n\t"
-       "movl    $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0      \n\t"
-       "1:                                                      \n\t"
-       "add     $8, %%esp                                       \n\t"
-       :"=rm"(rc)
-       :"0"(VINF_SUCCESS),
-        "ir"((uint32_t)HCPhysVmcs),        /* don't allow direct memory reference here, */
-        "ir"((uint32_t)(HCPhysVmcs >> 32)) /* this would not work with -fomit-frame-pointer */
-       :"memory"
-       );
-    return rc;
-
-# elif VMX_USE_MSC_INTRINSICS
-    unsigned char rcMsc = __vmx_vmclear(&HCPhysVmcs);
-    if (RT_LIKELY(rcMsc == 0))
-        return VINF_SUCCESS;
-    return VERR_VMX_INVALID_VMCS_PTR;
-
-# else
-    int rc = VINF_SUCCESS;
-    __asm
-    {
-        push    dword ptr [HCPhysVmcs + 4]
-        push    dword ptr [HCPhysVmcs]
-        _emit   0x66
-        _emit   0x0f
-        _emit   0xc7
-        _emit   0x34
-        _emit   0x24     /* VMCLEAR [esp] */
-        jnc     success
-        mov     dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
-success:
-        add     esp, 8
-    }
-    return rc;
-# endif
-}
-#endif
-
-
-/**
- * Executes VMPTRLD.
- *
- * @returns VBox status code.
- * @param   HCPhysVmcs       Physical address of VMCS structure.
- */
-#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS)
-DECLASM(int) VMXActivateVmcs(RTHCPHYS HCPhysVmcs);
-#else
-DECLINLINE(int) VMXActivateVmcs(RTHCPHYS HCPhysVmcs)
-{
-# if RT_INLINE_ASM_GNU_STYLE
-    int rc = VINF_SUCCESS;
-    __asm__ __volatile__ (
-       "push    %3                                              \n\t"
-       "push    %2                                              \n\t"
-       ".byte   0x0f, 0xc7, 0x34, 0x24  # VMPTRLD [esp]         \n\t"
-       "jnc     1f                                              \n\t"
-       "movl    $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0      \n\t"
-       "1:                                                      \n\t"
-       "add     $8, %%esp                                       \n\t"
-       :"=rm"(rc)
-       :"0"(VINF_SUCCESS),
-        "ir"((uint32_t)HCPhysVmcs),        /* don't allow direct memory reference here, */
-        "ir"((uint32_t)(HCPhysVmcs >> 32)) /* this will not work with -fomit-frame-pointer */
-       );
-    return rc;
-
-# elif VMX_USE_MSC_INTRINSICS
-    unsigned char rcMsc = __vmx_vmptrld(&HCPhysVmcs);
-    if (RT_LIKELY(rcMsc == 0))
-        return VINF_SUCCESS;
-    return VERR_VMX_INVALID_VMCS_PTR;
-
-# else
-    int rc = VINF_SUCCESS;
-    __asm
-    {
-        push    dword ptr [HCPhysVmcs + 4]
-        push    dword ptr [HCPhysVmcs]
-        _emit   0x0f
-        _emit   0xc7
-        _emit   0x34
-        _emit   0x24     /* VMPTRLD [esp] */
-        jnc     success
-        mov     dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
-
-success:
-        add     esp, 8
-    }
-    return rc;
-# endif
-}
-#endif
-
-
-/**
- * Executes VMPTRST.
- *
- * @returns VBox status code.
- * @param   pHCPhysVmcs    Where to store the physical address of the current
- *                         VMCS.
- */
-DECLASM(int) VMXGetActivatedVmcs(RTHCPHYS *pHCPhysVmcs);
-
-
-/**
- * Executes VMWRITE.
- *
- * @returns VBox status code.
- * @retval  VINF_SUCCESS.
- * @retval  VERR_VMX_INVALID_VMCS_PTR.
- * @retval  VERR_VMX_INVALID_VMCS_FIELD.
- *
- * @param   uFieldEnc       VMCS field encoding.
- * @param   u32Val          The 32-bit value to set.
- *
- * @remarks The values of the two status codes can be OR'ed together, the result
- *          will be VERR_VMX_INVALID_VMCS_PTR.
- */
-#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS)
-DECLASM(int) VMXWriteVmcs32(uint32_t uFieldEnc, uint32_t u32Val);
-#else
-DECLINLINE(int) VMXWriteVmcs32(uint32_t uFieldEnc, uint32_t u32Val)
-{
-# if RT_INLINE_ASM_GNU_STYLE
-    int rc = VINF_SUCCESS;
-    __asm__ __volatile__ (
-       ".byte  0x0f, 0x79, 0xc2        # VMWRITE eax, edx       \n\t"
-       "ja     2f                                               \n\t"
-       "je     1f                                               \n\t"
-       "movl   $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0       \n\t"
-       "jmp    2f                                               \n\t"
-       "1:                                                      \n\t"
-       "movl   $" RT_XSTR(VERR_VMX_INVALID_VMCS_FIELD)", %0     \n\t"
-       "2:                                                      \n\t"
-       :"=rm"(rc)
-       :"0"(VINF_SUCCESS),
-        "a"(uFieldEnc),
-        "d"(u32Val)
-       );
-    return rc;
-
-# elif VMX_USE_MSC_INTRINSICS
-     unsigned char rcMsc = __vmx_vmwrite(uFieldEnc, u32Val);
-     if (RT_LIKELY(rcMsc == 0))
-         return VINF_SUCCESS;
-     return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD;
-
-#else
-    int rc = VINF_SUCCESS;
-    __asm
-    {
-        push   dword ptr [u32Val]
-        mov    eax, [uFieldEnc]
-        _emit  0x0f
-        _emit  0x79
-        _emit  0x04
-        _emit  0x24     /* VMWRITE eax, [esp] */
-        jnc    valid_vmcs
-        mov    dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
-        jmp    the_end
-
-valid_vmcs:
-        jnz    the_end
-        mov    dword ptr [rc], VERR_VMX_INVALID_VMCS_FIELD
-the_end:
-        add    esp, 4
-    }
-    return rc;
-# endif
-}
-#endif
-
-/**
- * Executes VMWRITE.
- *
- * @returns VBox status code.
- * @retval  VINF_SUCCESS.
- * @retval  VERR_VMX_INVALID_VMCS_PTR.
- * @retval  VERR_VMX_INVALID_VMCS_FIELD.
- *
- * @param   uFieldEnc       The VMCS field encoding.
- * @param   u64Val          The 16, 32 or 64-bit value to set.
- *
- * @remarks The values of the two status codes can be OR'ed together, the result
- *          will be VERR_VMX_INVALID_VMCS_PTR.
- */
-#if !defined(RT_ARCH_X86)
-# if !VMX_USE_MSC_INTRINSICS || ARCH_BITS != 64
-DECLASM(int) VMXWriteVmcs64(uint32_t uFieldEnc, uint64_t u64Val);
-# else  /* VMX_USE_MSC_INTRINSICS */
-DECLINLINE(int) VMXWriteVmcs64(uint32_t uFieldEnc, uint64_t u64Val)
-{
-    unsigned char rcMsc = __vmx_vmwrite(uFieldEnc, u64Val);
-    if (RT_LIKELY(rcMsc == 0))
-        return VINF_SUCCESS;
-    return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD;
-}
-# endif /* VMX_USE_MSC_INTRINSICS */
-#else
-# define VMXWriteVmcs64(uFieldEnc, u64Val)    VMXWriteVmcs64Ex(pVCpu, uFieldEnc, u64Val) /** @todo dead ugly, picking up pVCpu like this */
-VMMR0DECL(int) VMXWriteVmcs64Ex(PVMCPU pVCpu, uint32_t uFieldEnc, uint64_t u64Val);
-#endif
-
-#if ARCH_BITS == 32
-# define VMXWriteVmcsHstN                       VMXWriteVmcs32
-# define VMXWriteVmcsGstN(uFieldEnc, u64Val)     VMXWriteVmcs64Ex(pVCpu, uFieldEnc, u64Val)
-#else  /* ARCH_BITS == 64 */
-# define VMXWriteVmcsHstN                       VMXWriteVmcs64
-# define VMXWriteVmcsGstN                       VMXWriteVmcs64
-#endif
-
-
-/**
- * Invalidate a page using INVEPT.
- *
- * @returns VBox status code.
- * @param   enmFlush        Type of flush.
- * @param   pDescriptor     Pointer to the descriptor.
- */
-DECLASM(int) VMXR0InvEPT(VMXTLBFLUSHEPT enmFlush, uint64_t *pDescriptor);
-
-
-/**
- * Invalidate a page using INVVPID.
- *
- * @returns VBox status code.
- * @param   enmFlush        Type of flush.
- * @param   pDescriptor     Pointer to the descriptor.
- */
-DECLASM(int) VMXR0InvVPID(VMXTLBFLUSHVPID enmFlush, uint64_t *pDescriptor);
-
-
-/**
- * Executes VMREAD for a 32-bit field.
- *
- * @returns VBox status code.
- * @retval  VINF_SUCCESS.
- * @retval  VERR_VMX_INVALID_VMCS_PTR.
- * @retval  VERR_VMX_INVALID_VMCS_FIELD.
- *
- * @param   uFieldEnc       The VMCS field encoding.
- * @param   pData           Where to store VMCS field value.
- *
- * @remarks The values of the two status codes can be OR'ed together, the result
- *          will be VERR_VMX_INVALID_VMCS_PTR.
- */
-#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS)
-DECLASM(int) VMXReadVmcs32(uint32_t uFieldEnc, uint32_t *pData);
-#else
-DECLINLINE(int) VMXReadVmcs32(uint32_t uFieldEnc, uint32_t *pData)
-{
-# if RT_INLINE_ASM_GNU_STYLE
-    int rc = VINF_SUCCESS;
-    __asm__ __volatile__ (
-       "movl   $" RT_XSTR(VINF_SUCCESS)", %0                     \n\t"
-       ".byte  0x0f, 0x78, 0xc2        # VMREAD eax, edx         \n\t"
-       "ja     2f                                                \n\t"
-       "je     1f                                                \n\t"
-       "movl   $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0        \n\t"
-       "jmp    2f                                                \n\t"
-       "1:                                                       \n\t"
-       "movl   $" RT_XSTR(VERR_VMX_INVALID_VMCS_FIELD)", %0      \n\t"
-       "2:                                                       \n\t"
-       :"=&r"(rc),
-        "=d"(*pData)
-       :"a"(uFieldEnc),
-        "d"(0)
-       );
-    return rc;
-
-# elif VMX_USE_MSC_INTRINSICS
-    unsigned char rcMsc;
-#  if ARCH_BITS == 32
-    rcMsc = __vmx_vmread(uFieldEnc, pData);
-#  else
-    uint64_t u64Tmp;
-    rcMsc = __vmx_vmread(uFieldEnc, &u64Tmp);
-    *pData = (uint32_t)u64Tmp;
-#  endif
-    if (RT_LIKELY(rcMsc == 0))
-        return VINF_SUCCESS;
-    return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD;
-
-#else
-    int rc = VINF_SUCCESS;
-    __asm
-    {
-        sub     esp, 4
-        mov     dword ptr [esp], 0
-        mov     eax, [uFieldEnc]
-        _emit   0x0f
-        _emit   0x78
-        _emit   0x04
-        _emit   0x24     /* VMREAD eax, [esp] */
-        mov     edx, pData
-        pop     dword ptr [edx]
-        jnc     valid_vmcs
-        mov     dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
-        jmp     the_end
-
-valid_vmcs:
-        jnz     the_end
-        mov     dword ptr [rc], VERR_VMX_INVALID_VMCS_FIELD
-the_end:
-    }
-    return rc;
-# endif
-}
-#endif
-
-/**
- * Executes VMREAD for a 64-bit field.
- *
- * @returns VBox status code.
- * @retval  VINF_SUCCESS.
- * @retval  VERR_VMX_INVALID_VMCS_PTR.
- * @retval  VERR_VMX_INVALID_VMCS_FIELD.
- *
- * @param   uFieldEnc       The VMCS field encoding.
- * @param   pData           Where to store VMCS field value.
- *
- * @remarks The values of the two status codes can be OR'ed together, the result
- *          will be VERR_VMX_INVALID_VMCS_PTR.
- */
-#if (!defined(RT_ARCH_X86) && !VMX_USE_MSC_INTRINSICS)
-DECLASM(int) VMXReadVmcs64(uint32_t uFieldEnc, uint64_t *pData);
-#else
-DECLINLINE(int) VMXReadVmcs64(uint32_t uFieldEnc, uint64_t *pData)
-{
-# if VMX_USE_MSC_INTRINSICS
-    unsigned char rcMsc;
-#  if ARCH_BITS == 32
-    size_t        uLow;
-    size_t        uHigh;
-    rcMsc  = __vmx_vmread(uFieldEnc, &uLow);
-    rcMsc |= __vmx_vmread(uFieldEnc + 1, &uHigh);
-    *pData = RT_MAKE_U64(uLow, uHigh);
-# else
-    rcMsc = __vmx_vmread(uFieldEnc, pData);
-# endif
-    if (RT_LIKELY(rcMsc == 0))
-        return VINF_SUCCESS;
-    return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD;
-
-# elif ARCH_BITS == 32
-    int rc;
-    uint32_t val_hi, val;
-    rc  = VMXReadVmcs32(uFieldEnc, &val);
-    rc |= VMXReadVmcs32(uFieldEnc + 1, &val_hi);
-    AssertRC(rc);
-    *pData = RT_MAKE_U64(val, val_hi);
-    return rc;
-
-# else
-#  error "Shouldn't be here..."
-# endif
-}
-#endif
-
-
-/**
- * Gets the last instruction error value from the current VMCS.
- *
- * @returns VBox status code.
- */
-DECLINLINE(uint32_t) VMXGetLastError(void)
-{
-#if ARCH_BITS == 64
-    uint64_t uLastError = 0;
-    int rc = VMXReadVmcs64(VMX_VMCS32_RO_VM_INSTR_ERROR, &uLastError);
-    AssertRC(rc);
-    return (uint32_t)uLastError;
-
-#else /* 32-bit host: */
-    uint32_t uLastError = 0;
-    int rc = VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &uLastError);
-    AssertRC(rc);
-    return uLastError;
-#endif
-}
-
-/** @} */
-
-/** @} */
-
-#endif
-
Index: trunk/include/VBox/vmm/hmvmxinline.h
===================================================================
--- trunk/include/VBox/vmm/hmvmxinline.h	(revision 76397)
+++ trunk/include/VBox/vmm/hmvmxinline.h	(revision 76397)
@@ -0,0 +1,740 @@
+/** @file
+ * HM - VMX Structures and Definitions. (VMM)
+ */
+
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_hmvmxinline_h
+#define ___VBox_vmm_hmvmxinline_h
+
+#include <VBox/vmm/hm_vmx.h>
+#include <VBox/err.h>
+
+/* In Visual C++ versions prior to 2012, the vmx intrinsics are only available
+   when targeting AMD64. */
+#if RT_INLINE_ASM_USES_INTRIN >= 16 && defined(RT_ARCH_AMD64)
+# pragma warning(push)
+# pragma warning(disable:4668) /* Several incorrect __cplusplus uses. */
+# pragma warning(disable:4255) /* Incorrect __slwpcb prototype. */
+# include <intrin.h>
+# pragma warning(pop)
+/* We always want them as intrinsics, no functions. */
+# pragma intrinsic(__vmx_on)
+# pragma intrinsic(__vmx_off)
+# pragma intrinsic(__vmx_vmclear)
+# pragma intrinsic(__vmx_vmptrld)
+# pragma intrinsic(__vmx_vmread)
+# pragma intrinsic(__vmx_vmwrite)
+# define VMX_USE_MSC_INTRINSICS 1
+#else
+# define VMX_USE_MSC_INTRINSICS 0
+#endif
+
+
+/** @defgroup grp_hm_vmx_inline    VMX Inline Helpers
+ * @ingroup grp_hm_vmx
+ * @{
+ */
+/**
+ * Gets the effective width of a VMCS field given it's encoding adjusted for
+ * HIGH/FULL access for 64-bit fields.
+ *
+ * @returns The effective VMCS field width.
+ * @param   uFieldEnc   The VMCS field encoding.
+ *
+ * @remarks Warning! This function does not verify the encoding is for a valid and
+ *          supported VMCS field.
+ */
+DECLINLINE(uint8_t) HMVmxGetVmcsFieldWidthEff(uint32_t uFieldEnc)
+{
+    /* Only the "HIGH" parts of all 64-bit fields have bit 0 set. */
+    if (uFieldEnc & RT_BIT(0))
+        return VMXVMCSFIELDWIDTH_32BIT;
+
+    /* Bits 13:14 contains the width of the VMCS field, see VMXVMCSFIELDWIDTH_XXX. */
+    return (uFieldEnc >> 13) & 0x3;
+}
+
+/**
+ * Returns whether the given VMCS field is a read-only VMCS field or not.
+ *
+ * @returns @c true if it's a read-only field, @c false otherwise.
+ * @param   uFieldEnc   The VMCS field encoding.
+ *
+ * @remarks Warning! This function does not verify the encoding is for a valid and
+ *          supported VMCS field.
+ */
+DECLINLINE(bool) HMVmxIsVmcsFieldReadOnly(uint32_t uFieldEnc)
+{
+    /* See Intel spec. B.4.2 "Natural-Width Read-Only Data Fields". */
+    return (RT_BF_GET(uFieldEnc, VMX_BF_VMCS_ENC_TYPE) == VMXVMCSFIELDTYPE_VMEXIT_INFO);
+}
+
+/**
+ * Returns whether the given VM-entry interruption-information type is valid or not.
+ *
+ * @returns @c true if it's a valid type, @c false otherwise.
+ * @param   fSupportsMTF    Whether the Monitor-Trap Flag CPU feature is supported.
+ * @param   uType           The VM-entry interruption-information type.
+ */
+DECLINLINE(bool) HMVmxIsEntryIntInfoTypeValid(bool fSupportsMTF, uint8_t uType)
+{
+    /* See Intel spec. 26.2.1.3 "VM-Entry Control Fields". */
+    switch (uType)
+    {
+        case VMX_ENTRY_INT_INFO_TYPE_EXT_INT:
+        case VMX_ENTRY_INT_INFO_TYPE_NMI:
+        case VMX_ENTRY_INT_INFO_TYPE_HW_XCPT:
+        case VMX_ENTRY_INT_INFO_TYPE_SW_INT:
+        case VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT:
+        case VMX_ENTRY_INT_INFO_TYPE_SW_XCPT:           return true;
+        case VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT:       return fSupportsMTF;
+        default:
+            return false;
+    }
+}
+
+/**
+ * Returns whether the given VM-entry interruption-information vector and type
+ * combination is valid or not.
+ *
+ * @returns @c true if it's a valid vector/type combination, @c false otherwise.
+ * @param   uVector     The VM-entry interruption-information vector.
+ * @param   uType       The VM-entry interruption-information type.
+ *
+ * @remarks Warning! This function does not validate the type field individually.
+ *          Use it after verifying type is valid using HMVmxIsEntryIntInfoTypeValid.
+ */
+DECLINLINE(bool) HMVmxIsEntryIntInfoVectorValid(uint8_t uVector, uint8_t uType)
+{
+    /* See Intel spec. 26.2.1.3 "VM-Entry Control Fields". */
+    if (   uType == VMX_ENTRY_INT_INFO_TYPE_NMI
+        && uVector != X86_XCPT_NMI)
+        return false;
+    if (   uType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
+        && uVector > X86_XCPT_LAST)
+        return false;
+    if (   uType == VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT
+        && uVector != VMX_ENTRY_INT_INFO_VECTOR_MTF)
+        return false;
+    return true;
+}
+
+
+/**
+ * Returns whether or not the VM-exit is trap-like or fault-like.
+ *
+ * @returns @c true if it's a trap-like VM-exit, @c false otherwise.
+ * @param   uExitReason     The VM-exit reason.
+ *
+ * @remarks Warning! This does not validate the VM-exit reason.
+ */
+DECLINLINE(bool) HMVmxIsVmexitTrapLike(uint32_t uExitReason)
+{
+    /*
+     * Trap-like VM-exits - The instruction causing the VM-exit completes before the
+     * VM-exit occurs.
+     *
+     * Fault-like VM-exits - The instruction causing the VM-exit is not completed before
+     * the VM-exit occurs.
+     *
+     * See Intel spec. 25.5.2 "Monitor Trap Flag".
+     * See Intel spec. 29.1.4 "EOI Virtualization".
+     * See Intel spec. 29.4.3.3 "APIC-Write VM Exits".
+     * See Intel spec. 29.1.2 "TPR Virtualization".
+     */
+    /** @todo NSTVMX: r=ramshankar: What about VM-exits due to debug traps (single-step,
+     *        I/O breakpoints, data breakpoints), debug exceptions (data breakpoint)
+     *        delayed by MovSS blocking, machine-check exceptions. */
+    switch (uExitReason)
+    {
+        case VMX_EXIT_MTF:
+        case VMX_EXIT_VIRTUALIZED_EOI:
+        case VMX_EXIT_APIC_WRITE:
+        case VMX_EXIT_TPR_BELOW_THRESHOLD:
+            return true;
+    }
+    return false;
+}
+
+
+/**
+ * Returns whether the VM-entry is vectoring or not given the VM-entry interruption
+ * information field.
+ *
+ * @returns @c true if the VM-entry is vectoring, @c false otherwise.
+ * @param   uEntryIntInfo       The VM-entry interruption information field.
+ * @param   pEntryIntInfoType   The VM-entry interruption information type field.
+ *                              Optional, can be NULL. Only updated when this
+ *                              function returns @c true.
+ */
+DECLINLINE(bool) HMVmxIsVmentryVectoring(uint32_t uEntryIntInfo, uint8_t *pEntryIntInfoType)
+{
+    /*
+     * The definition of what is a vectoring VM-entry is taken
+     * from Intel spec. 26.6 "Special Features of VM Entry".
+     */
+    if (!VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo))
+        return false;
+
+    /* Scope and keep variable defines on top to satisy archaic c89 nonsense. */
+    {
+        uint8_t const uType = VMX_ENTRY_INT_INFO_TYPE(uEntryIntInfo);
+        switch (uType)
+        {
+            case VMX_ENTRY_INT_INFO_TYPE_EXT_INT:
+            case VMX_ENTRY_INT_INFO_TYPE_NMI:
+            case VMX_ENTRY_INT_INFO_TYPE_HW_XCPT:
+            case VMX_ENTRY_INT_INFO_TYPE_SW_INT:
+            case VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT:
+            case VMX_ENTRY_INT_INFO_TYPE_SW_XCPT:
+            {
+                if (pEntryIntInfoType)
+                    *pEntryIntInfoType = uType;
+                return true;
+            }
+        }
+    }
+    return false;
+}
+/** @} */
+
+
+/** @defgroup grp_hm_vmx_asm    VMX Assembly Helpers
+ * @{
+ */
+
+/**
+ * Restores some host-state fields that need not be done on every VM-exit.
+ *
+ * @returns VBox status code.
+ * @param   fRestoreHostFlags   Flags of which host registers needs to be
+ *                              restored.
+ * @param   pRestoreHost        Pointer to the host-restore structure.
+ */
+DECLASM(int) VMXRestoreHostState(uint32_t fRestoreHostFlags, PVMXRESTOREHOST pRestoreHost);
+
+
+/**
+ * Dispatches an NMI to the host.
+ */
+DECLASM(int) VMXDispatchHostNmi(void);
+
+
+/**
+ * Executes VMXON.
+ *
+ * @returns VBox status code.
+ * @param   HCPhysVmxOn      Physical address of VMXON structure.
+ */
+#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS)
+DECLASM(int) VMXEnable(RTHCPHYS HCPhysVmxOn);
+#else
+DECLINLINE(int) VMXEnable(RTHCPHYS HCPhysVmxOn)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    int rc = VINF_SUCCESS;
+    __asm__ __volatile__ (
+       "push     %3                                             \n\t"
+       "push     %2                                             \n\t"
+       ".byte    0xf3, 0x0f, 0xc7, 0x34, 0x24  # VMXON [esp]    \n\t"
+       "ja       2f                                             \n\t"
+       "je       1f                                             \n\t"
+       "movl     $" RT_XSTR(VERR_VMX_INVALID_VMXON_PTR)", %0    \n\t"
+       "jmp      2f                                             \n\t"
+       "1:                                                      \n\t"
+       "movl     $" RT_XSTR(VERR_VMX_VMXON_FAILED)", %0         \n\t"
+       "2:                                                      \n\t"
+       "add      $8, %%esp                                      \n\t"
+       :"=rm"(rc)
+       :"0"(VINF_SUCCESS),
+        "ir"((uint32_t)HCPhysVmxOn),        /* don't allow direct memory reference here, */
+        "ir"((uint32_t)(HCPhysVmxOn >> 32)) /* this would not work with -fomit-frame-pointer */
+       :"memory"
+       );
+    return rc;
+
+# elif VMX_USE_MSC_INTRINSICS
+    unsigned char rcMsc = __vmx_on(&HCPhysVmxOn);
+    if (RT_LIKELY(rcMsc == 0))
+        return VINF_SUCCESS;
+    return rcMsc == 2 ? VERR_VMX_INVALID_VMXON_PTR : VERR_VMX_VMXON_FAILED;
+
+# else
+    int rc = VINF_SUCCESS;
+    __asm
+    {
+        push    dword ptr [HCPhysVmxOn + 4]
+        push    dword ptr [HCPhysVmxOn]
+        _emit   0xf3
+        _emit   0x0f
+        _emit   0xc7
+        _emit   0x34
+        _emit   0x24     /* VMXON [esp] */
+        jnc     vmxon_good
+        mov     dword ptr [rc], VERR_VMX_INVALID_VMXON_PTR
+        jmp     the_end
+
+vmxon_good:
+        jnz     the_end
+        mov     dword ptr [rc], VERR_VMX_VMXON_FAILED
+the_end:
+        add     esp, 8
+    }
+    return rc;
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMXOFF.
+ */
+#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS)
+DECLASM(void) VMXDisable(void);
+#else
+DECLINLINE(void) VMXDisable(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    __asm__ __volatile__ (
+       ".byte 0x0f, 0x01, 0xc4  # VMXOFF                        \n\t"
+       );
+
+# elif VMX_USE_MSC_INTRINSICS
+    __vmx_off();
+
+# else
+    __asm
+    {
+        _emit   0x0f
+        _emit   0x01
+        _emit   0xc4   /* VMXOFF */
+    }
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMCLEAR.
+ *
+ * @returns VBox status code.
+ * @param   HCPhysVmcs       Physical address of VM control structure.
+ */
+#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS)
+DECLASM(int) VMXClearVmcs(RTHCPHYS HCPhysVmcs);
+#else
+DECLINLINE(int) VMXClearVmcs(RTHCPHYS HCPhysVmcs)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    int rc = VINF_SUCCESS;
+    __asm__ __volatile__ (
+       "push    %3                                              \n\t"
+       "push    %2                                              \n\t"
+       ".byte   0x66, 0x0f, 0xc7, 0x34, 0x24  # VMCLEAR [esp]   \n\t"
+       "jnc     1f                                              \n\t"
+       "movl    $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0      \n\t"
+       "1:                                                      \n\t"
+       "add     $8, %%esp                                       \n\t"
+       :"=rm"(rc)
+       :"0"(VINF_SUCCESS),
+        "ir"((uint32_t)HCPhysVmcs),        /* don't allow direct memory reference here, */
+        "ir"((uint32_t)(HCPhysVmcs >> 32)) /* this would not work with -fomit-frame-pointer */
+       :"memory"
+       );
+    return rc;
+
+# elif VMX_USE_MSC_INTRINSICS
+    unsigned char rcMsc = __vmx_vmclear(&HCPhysVmcs);
+    if (RT_LIKELY(rcMsc == 0))
+        return VINF_SUCCESS;
+    return VERR_VMX_INVALID_VMCS_PTR;
+
+# else
+    int rc = VINF_SUCCESS;
+    __asm
+    {
+        push    dword ptr [HCPhysVmcs + 4]
+        push    dword ptr [HCPhysVmcs]
+        _emit   0x66
+        _emit   0x0f
+        _emit   0xc7
+        _emit   0x34
+        _emit   0x24     /* VMCLEAR [esp] */
+        jnc     success
+        mov     dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
+success:
+        add     esp, 8
+    }
+    return rc;
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMPTRLD.
+ *
+ * @returns VBox status code.
+ * @param   HCPhysVmcs       Physical address of VMCS structure.
+ */
+#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS)
+DECLASM(int) VMXActivateVmcs(RTHCPHYS HCPhysVmcs);
+#else
+DECLINLINE(int) VMXActivateVmcs(RTHCPHYS HCPhysVmcs)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    int rc = VINF_SUCCESS;
+    __asm__ __volatile__ (
+       "push    %3                                              \n\t"
+       "push    %2                                              \n\t"
+       ".byte   0x0f, 0xc7, 0x34, 0x24  # VMPTRLD [esp]         \n\t"
+       "jnc     1f                                              \n\t"
+       "movl    $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0      \n\t"
+       "1:                                                      \n\t"
+       "add     $8, %%esp                                       \n\t"
+       :"=rm"(rc)
+       :"0"(VINF_SUCCESS),
+        "ir"((uint32_t)HCPhysVmcs),        /* don't allow direct memory reference here, */
+        "ir"((uint32_t)(HCPhysVmcs >> 32)) /* this will not work with -fomit-frame-pointer */
+       );
+    return rc;
+
+# elif VMX_USE_MSC_INTRINSICS
+    unsigned char rcMsc = __vmx_vmptrld(&HCPhysVmcs);
+    if (RT_LIKELY(rcMsc == 0))
+        return VINF_SUCCESS;
+    return VERR_VMX_INVALID_VMCS_PTR;
+
+# else
+    int rc = VINF_SUCCESS;
+    __asm
+    {
+        push    dword ptr [HCPhysVmcs + 4]
+        push    dword ptr [HCPhysVmcs]
+        _emit   0x0f
+        _emit   0xc7
+        _emit   0x34
+        _emit   0x24     /* VMPTRLD [esp] */
+        jnc     success
+        mov     dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
+
+success:
+        add     esp, 8
+    }
+    return rc;
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMPTRST.
+ *
+ * @returns VBox status code.
+ * @param   pHCPhysVmcs    Where to store the physical address of the current
+ *                         VMCS.
+ */
+DECLASM(int) VMXGetActivatedVmcs(RTHCPHYS *pHCPhysVmcs);
+
+
+/**
+ * Executes VMWRITE.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS.
+ * @retval  VERR_VMX_INVALID_VMCS_PTR.
+ * @retval  VERR_VMX_INVALID_VMCS_FIELD.
+ *
+ * @param   uFieldEnc       VMCS field encoding.
+ * @param   u32Val          The 32-bit value to set.
+ *
+ * @remarks The values of the two status codes can be OR'ed together, the result
+ *          will be VERR_VMX_INVALID_VMCS_PTR.
+ */
+#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS)
+DECLASM(int) VMXWriteVmcs32(uint32_t uFieldEnc, uint32_t u32Val);
+#else
+DECLINLINE(int) VMXWriteVmcs32(uint32_t uFieldEnc, uint32_t u32Val)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    int rc = VINF_SUCCESS;
+    __asm__ __volatile__ (
+       ".byte  0x0f, 0x79, 0xc2        # VMWRITE eax, edx       \n\t"
+       "ja     2f                                               \n\t"
+       "je     1f                                               \n\t"
+       "movl   $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0       \n\t"
+       "jmp    2f                                               \n\t"
+       "1:                                                      \n\t"
+       "movl   $" RT_XSTR(VERR_VMX_INVALID_VMCS_FIELD)", %0     \n\t"
+       "2:                                                      \n\t"
+       :"=rm"(rc)
+       :"0"(VINF_SUCCESS),
+        "a"(uFieldEnc),
+        "d"(u32Val)
+       );
+    return rc;
+
+# elif VMX_USE_MSC_INTRINSICS
+     unsigned char rcMsc = __vmx_vmwrite(uFieldEnc, u32Val);
+     if (RT_LIKELY(rcMsc == 0))
+         return VINF_SUCCESS;
+     return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD;
+
+#else
+    int rc = VINF_SUCCESS;
+    __asm
+    {
+        push   dword ptr [u32Val]
+        mov    eax, [uFieldEnc]
+        _emit  0x0f
+        _emit  0x79
+        _emit  0x04
+        _emit  0x24     /* VMWRITE eax, [esp] */
+        jnc    valid_vmcs
+        mov    dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
+        jmp    the_end
+
+valid_vmcs:
+        jnz    the_end
+        mov    dword ptr [rc], VERR_VMX_INVALID_VMCS_FIELD
+the_end:
+        add    esp, 4
+    }
+    return rc;
+# endif
+}
+#endif
+
+/**
+ * Executes VMWRITE.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS.
+ * @retval  VERR_VMX_INVALID_VMCS_PTR.
+ * @retval  VERR_VMX_INVALID_VMCS_FIELD.
+ *
+ * @param   uFieldEnc       The VMCS field encoding.
+ * @param   u64Val          The 16, 32 or 64-bit value to set.
+ *
+ * @remarks The values of the two status codes can be OR'ed together, the result
+ *          will be VERR_VMX_INVALID_VMCS_PTR.
+ */
+#if !defined(RT_ARCH_X86)
+# if !VMX_USE_MSC_INTRINSICS || ARCH_BITS != 64
+DECLASM(int) VMXWriteVmcs64(uint32_t uFieldEnc, uint64_t u64Val);
+# else  /* VMX_USE_MSC_INTRINSICS */
+DECLINLINE(int) VMXWriteVmcs64(uint32_t uFieldEnc, uint64_t u64Val)
+{
+    unsigned char rcMsc = __vmx_vmwrite(uFieldEnc, u64Val);
+    if (RT_LIKELY(rcMsc == 0))
+        return VINF_SUCCESS;
+    return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD;
+}
+# endif /* VMX_USE_MSC_INTRINSICS */
+#else
+# define VMXWriteVmcs64(uFieldEnc, u64Val)    VMXWriteVmcs64Ex(pVCpu, uFieldEnc, u64Val) /** @todo dead ugly, picking up pVCpu like this */
+VMMR0DECL(int) VMXWriteVmcs64Ex(PVMCPU pVCpu, uint32_t uFieldEnc, uint64_t u64Val);
+#endif
+
+#if ARCH_BITS == 32
+# define VMXWriteVmcsHstN                       VMXWriteVmcs32
+# define VMXWriteVmcsGstN(uFieldEnc, u64Val)     VMXWriteVmcs64Ex(pVCpu, uFieldEnc, u64Val)
+#else  /* ARCH_BITS == 64 */
+# define VMXWriteVmcsHstN                       VMXWriteVmcs64
+# define VMXWriteVmcsGstN                       VMXWriteVmcs64
+#endif
+
+
+/**
+ * Invalidate a page using INVEPT.
+ *
+ * @returns VBox status code.
+ * @param   enmFlush        Type of flush.
+ * @param   pDescriptor     Pointer to the descriptor.
+ */
+DECLASM(int) VMXR0InvEPT(VMXTLBFLUSHEPT enmFlush, uint64_t *pDescriptor);
+
+
+/**
+ * Invalidate a page using INVVPID.
+ *
+ * @returns VBox status code.
+ * @param   enmFlush        Type of flush.
+ * @param   pDescriptor     Pointer to the descriptor.
+ */
+DECLASM(int) VMXR0InvVPID(VMXTLBFLUSHVPID enmFlush, uint64_t *pDescriptor);
+
+
+/**
+ * Executes VMREAD for a 32-bit field.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS.
+ * @retval  VERR_VMX_INVALID_VMCS_PTR.
+ * @retval  VERR_VMX_INVALID_VMCS_FIELD.
+ *
+ * @param   uFieldEnc       The VMCS field encoding.
+ * @param   pData           Where to store VMCS field value.
+ *
+ * @remarks The values of the two status codes can be OR'ed together, the result
+ *          will be VERR_VMX_INVALID_VMCS_PTR.
+ */
+#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS)
+DECLASM(int) VMXReadVmcs32(uint32_t uFieldEnc, uint32_t *pData);
+#else
+DECLINLINE(int) VMXReadVmcs32(uint32_t uFieldEnc, uint32_t *pData)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+    int rc = VINF_SUCCESS;
+    __asm__ __volatile__ (
+       "movl   $" RT_XSTR(VINF_SUCCESS)", %0                     \n\t"
+       ".byte  0x0f, 0x78, 0xc2        # VMREAD eax, edx         \n\t"
+       "ja     2f                                                \n\t"
+       "je     1f                                                \n\t"
+       "movl   $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0        \n\t"
+       "jmp    2f                                                \n\t"
+       "1:                                                       \n\t"
+       "movl   $" RT_XSTR(VERR_VMX_INVALID_VMCS_FIELD)", %0      \n\t"
+       "2:                                                       \n\t"
+       :"=&r"(rc),
+        "=d"(*pData)
+       :"a"(uFieldEnc),
+        "d"(0)
+       );
+    return rc;
+
+# elif VMX_USE_MSC_INTRINSICS
+    unsigned char rcMsc;
+#  if ARCH_BITS == 32
+    rcMsc = __vmx_vmread(uFieldEnc, pData);
+#  else
+    uint64_t u64Tmp;
+    rcMsc = __vmx_vmread(uFieldEnc, &u64Tmp);
+    *pData = (uint32_t)u64Tmp;
+#  endif
+    if (RT_LIKELY(rcMsc == 0))
+        return VINF_SUCCESS;
+    return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD;
+
+#else
+    int rc = VINF_SUCCESS;
+    __asm
+    {
+        sub     esp, 4
+        mov     dword ptr [esp], 0
+        mov     eax, [uFieldEnc]
+        _emit   0x0f
+        _emit   0x78
+        _emit   0x04
+        _emit   0x24     /* VMREAD eax, [esp] */
+        mov     edx, pData
+        pop     dword ptr [edx]
+        jnc     valid_vmcs
+        mov     dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
+        jmp     the_end
+
+valid_vmcs:
+        jnz     the_end
+        mov     dword ptr [rc], VERR_VMX_INVALID_VMCS_FIELD
+the_end:
+    }
+    return rc;
+# endif
+}
+#endif
+
+/**
+ * Executes VMREAD for a 64-bit field.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS.
+ * @retval  VERR_VMX_INVALID_VMCS_PTR.
+ * @retval  VERR_VMX_INVALID_VMCS_FIELD.
+ *
+ * @param   uFieldEnc       The VMCS field encoding.
+ * @param   pData           Where to store VMCS field value.
+ *
+ * @remarks The values of the two status codes can be OR'ed together, the result
+ *          will be VERR_VMX_INVALID_VMCS_PTR.
+ */
+#if (!defined(RT_ARCH_X86) && !VMX_USE_MSC_INTRINSICS)
+DECLASM(int) VMXReadVmcs64(uint32_t uFieldEnc, uint64_t *pData);
+#else
+DECLINLINE(int) VMXReadVmcs64(uint32_t uFieldEnc, uint64_t *pData)
+{
+# if VMX_USE_MSC_INTRINSICS
+    unsigned char rcMsc;
+#  if ARCH_BITS == 32
+    size_t        uLow;
+    size_t        uHigh;
+    rcMsc  = __vmx_vmread(uFieldEnc, &uLow);
+    rcMsc |= __vmx_vmread(uFieldEnc + 1, &uHigh);
+    *pData = RT_MAKE_U64(uLow, uHigh);
+# else
+    rcMsc = __vmx_vmread(uFieldEnc, pData);
+# endif
+    if (RT_LIKELY(rcMsc == 0))
+        return VINF_SUCCESS;
+    return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD;
+
+# elif ARCH_BITS == 32
+    int rc;
+    uint32_t val_hi, val;
+    rc  = VMXReadVmcs32(uFieldEnc, &val);
+    rc |= VMXReadVmcs32(uFieldEnc + 1, &val_hi);
+    AssertRC(rc);
+    *pData = RT_MAKE_U64(val, val_hi);
+    return rc;
+
+# else
+#  error "Shouldn't be here..."
+# endif
+}
+#endif
+
+
+/**
+ * Gets the last instruction error value from the current VMCS.
+ *
+ * @returns VBox status code.
+ */
+DECLINLINE(uint32_t) VMXGetLastError(void)
+{
+#if ARCH_BITS == 64
+    uint64_t uLastError = 0;
+    int rc = VMXReadVmcs64(VMX_VMCS32_RO_VM_INSTR_ERROR, &uLastError);
+    AssertRC(rc);
+    return (uint32_t)uLastError;
+
+#else /* 32-bit host: */
+    uint32_t uLastError = 0;
+    int rc = VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &uLastError);
+    AssertRC(rc);
+    return uLastError;
+#endif
+}
+
+/** @} */
+
+#endif
+
