Index: trunk/include/VBox/vmm/cpum.h
===================================================================
--- trunk/include/VBox/vmm/cpum.h	(revision 51332)
+++ trunk/include/VBox/vmm/cpum.h	(revision 51333)
@@ -595,4 +595,6 @@
     kCpumMsrRdFn_AmdFam14hIbsBrTarget,
 
+    kCpumMsrRdFn_Gim,
+
     /** End of valid MSR read function indexes. */
     kCpumMsrRdFn_End
@@ -817,4 +819,6 @@
     kCpumMsrWrFn_AmdFam14hIbsBrTarget,
 
+    kCpumMsrWrFn_Gim,
+
     /** End of valid MSR write function indexes. */
     kCpumMsrWrFn_End
Index: trunk/include/VBox/vmm/gim.h
===================================================================
--- trunk/include/VBox/vmm/gim.h	(revision 51332)
+++ trunk/include/VBox/vmm/gim.h	(revision 51333)
@@ -31,4 +31,10 @@
 #include <VBox/param.h>
 
+#include <VBox/vmm/cpum.h>
+
+/** The value used to specify that VirtualBox must use the newest
+ *  implementation version of the GIM provider. */
+#define GIM_VERSION_LATEST                  UINT32_C(0)
+
 RT_C_DECLS_BEGIN
 
@@ -40,19 +46,20 @@
  * Providers identifiers.
  */
-typedef enum GIMPROVIDER
+typedef enum GIMPROVIDERID
 {
     /** None. */
-    GIMPROVIDER_NONE = 0,
+    GIMPROVIDERID_NONE = 0,
     /** Minimal. */
-    GIMPROVIDER_MINIMAL,
+    GIMPROVIDERID_MINIMAL,
     /** Microsoft Hyper-V. */
-    GIMPROVIDER_HYPERV,
+    GIMPROVIDERID_HYPERV,
     /** Linux KVM Interface. */
-    GIMPROVIDER_KVM,
+    GIMPROVIDERID_KVM,
     /** Ensure 32-bit type. */
-    GIMPROVIDER_32BIT_HACK = 0x7fffffff
-} GIMPROVIDER;
+    GIMPROVIDERID_32BIT_HACK = 0x7fffffff
+} GIMPROVIDERID;
 
 
+#if 0
 /**
  * A GIM Hypercall handler.
@@ -64,4 +71,33 @@
 /** Pointer to a GIM hypercall handler. */
 typedef FNGIMHYPERCALL *PFNGIMHYPERCALL;
+
+/**
+ * A GIM MSR-read handler.
+ *
+ * @returns VBox status code.
+ * @param   pVM             Pointer to the VMCPU.
+ * @param   idMsr           The MSR being read.
+ * @param   pRange          The range that the MSR belongs to.
+ * @param   puValue         Where to store the value of the MSR.
+ */
+typedef DECLCALLBACK(int) FNGIMRDMSR(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue);
+/** Pointer to a GIM MSR-read handler. */
+typedef FNGIMRDMSR *PFNGIMRDMSR;
+
+/**
+ * A GIM MSR-write handler.
+ *
+ * @returns VBox status code.
+ * @param   pVM             Pointer to the VMCPU.
+ * @param   idMsr           The MSR being written.
+ * @param   pRange          The range that the MSR belongs to.
+ * @param   uValue          The value to set, ignored bits masked.
+ * @param   uRawValue       The raw value with the ignored bits not masked.
+ */
+typedef DECLCALLBACK(int) FNGIMWRMSR(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue);
+/** Pointer to a GIM MSR-write handler. */
+typedef FNGIMWRMSR *PFNGIMWRMSR;
+#endif
+
 
 #ifdef IN_RC
@@ -88,20 +124,13 @@
  * @{
  */
-VMMR3_INT_DECL(int)             GIMR3Init(PVM pVM);
-VMMR3_INT_DECL(int)             GIMR3Term(PVM pVM);
+VMMR3_INT_DECL(int)     GIMR3Init(PVM pVM);
+VMMR3_INT_DECL(int)     GIMR3Term(PVM pVM);
 /** @} */
 #endif /* IN_RING3 */
 
-
-/**
- * Checks whether GIM is being used by this VM.
- *
- * @retval  @c true if used.
- * @retval  @c false if no GIM provider ("none") is used.
- *
- * @param   pVM       Pointer to the VM.
- * @internal
- */
-VMMDECL(bool)                   GIMIsEnabled(PVM pVM);
+VMMDECL(bool)           GIMIsEnabled(PVM pVM);
+VMM_INT_DECL(int)       GIMHypercall(PVMCPU pVCpu, PCPUMCTX pCtx);
+VMM_INT_DECL(int)       GIMReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue);
+VMM_INT_DECL(int)       GIMWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue);
 
 /** @} */
Index: trunk/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp	(revision 51332)
+++ trunk/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp	(revision 51333)
@@ -24,4 +24,5 @@
 #include <VBox/vmm/hm.h>
 #include <VBox/vmm/tm.h>
+#include <VBox/vmm/gim.h>
 #include "CPUMInternal.h"
 #include <VBox/vmm/vm.h>
@@ -4388,4 +4389,25 @@
 }
 
+
+
+/*
+ * GIM MSRs.
+ * GIM MSRs.
+ * GIM MSRs.
+ */
+
+
+/** @callback_method_impl{FNCPUMRDMSR} */
+static DECLCALLBACK(int) cpumMsrRd_Gim(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    return GIMReadMsr(pVCpu, idMsr, pRange, puValue);
+}
+
+
+/** @callback_method_impl{FNCPUMWRMSR} */
+static DECLCALLBACK(int) cpumMsrWr_Gim(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    return GIMWriteMsr(pVCpu, idMsr, pRange, uValue, uRawValue);
+}
 
 
@@ -4646,4 +4668,6 @@
     cpumMsrRd_AmdFam10hIbsCtl,
     cpumMsrRd_AmdFam14hIbsBrTarget,
+
+    cpumMsrRd_Gim
 };
 
@@ -4860,4 +4884,6 @@
     cpumMsrWr_AmdFam10hIbsCtl,
     cpumMsrWr_AmdFam14hIbsBrTarget,
+
+    cpumMsrWr_Gim
 };
 
Index: trunk/src/VBox/VMM/VMMAll/GIMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/GIMAll.cpp	(revision 51332)
+++ trunk/src/VBox/VMM/VMMAll/GIMAll.cpp	(revision 51333)
@@ -22,7 +22,21 @@
 #define LOG_GROUP LOG_GROUP_GIM
 #include "GIMInternal.h"
+#include <VBox/err.h>
 #include <VBox/vmm/vm.h>
 
+/* Include all the providers. */
+#include "GIMHvInternal.h"
+#include "GIMMinimalInternal.h"
 
+
+/**
+ * Checks whether GIM is being used by this VM.
+ *
+ * @retval  @c true if used.
+ * @retval  @c false if no GIM provider ("none") is used.
+ *
+ * @param   pVM       Pointer to the VM.
+ * @internal
+ */
 VMMDECL(bool) GIMIsEnabled(PVM pVM)
 {
@@ -31,4 +45,11 @@
 
 
+/**
+ * Implements a GIM hypercall with the provider configured for the VM.
+ *
+ * @returns VBox status code.
+ * @param   pVCpu       Pointer to the VMCPU.
+ * @param   pCtx        Pointer to the guest-CPU context.
+ */
 VMM_INT_DECL(int) GIMHypercall(PVMCPU pVCpu, PCPUMCTX pCtx)
 {
@@ -37,5 +58,68 @@
     VMCPU_ASSERT_EMT(pVCpu);
 
-    return pVM->gim.s.CTX_SUFF(pfnHypercall)(pVCpu, pCtx);
+    switch (pVM->gim.s.enmProviderId)
+    {
+        case GIMPROVIDERID_HYPERV:
+            return GIMHvHypercall(pVCpu, pCtx);
+
+        default:
+            AssertMsgFailed(("GIMHypercall: for unknown provider %u\n", pVM->gim.s.enmProviderId));
+            return VERR_INTERNAL_ERROR_5; /** @todo Define and use VERR_GIM_HYPERCALL_UNEXPECTED */;
+    }
 }
 
+
+/**
+ * Invokes the read-MSR handler for the GIM provider configured for the VM.
+ *
+ * @returns VBox status code.
+ * @param   pVCpu       Pointer to the VMCPU.
+ * @param   idMsr       The MSR to read.
+ * @param   pRange      The range this MSR belongs to.
+ * @param   puValue     Where to store the MSR value read.
+ */
+VMM_INT_DECL(int) GIMReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    PVM pVM = pVCpu->CTX_SUFF(pVM);
+    Assert(GIMIsEnabled(pVM));
+    VMCPU_ASSERT_EMT(pVCpu);
+
+    switch (pVM->gim.s.enmProviderId)
+    {
+        case GIMPROVIDERID_HYPERV:
+            return GIMHvReadMsr(pVCpu, idMsr, pRange, puValue);
+
+        default:
+            AssertMsgFailed(("GIMReadMsr: for unknown provider %u idMsr=%#RX32 -> #GP(0)", pVM->gim.s.enmProviderId, idMsr));
+            return VERR_CPUM_RAISE_GP_0;
+    }
+}
+
+
+/**
+ * Invokes the write-MSR handler for the GIM provider configured for the VM.
+ *
+ * @returns VBox status code.
+ * @param   pVCpu       Pointer to the VMCPU.
+ * @param   idMsr       The MSR to write.
+ * @param   pRange      The range this MSR belongs to.
+ * @param   uValue      The value to set, ignored bits masked.
+ * @param   uRawValue   The raw value with the ignored bits not masked.
+ */
+VMM_INT_DECL(int) GIMWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    PVM pVM = pVCpu->CTX_SUFF(pVM);
+    Assert(GIMIsEnabled(pVM));
+    VMCPU_ASSERT_EMT(pVCpu);
+
+    switch (pVM->gim.s.enmProviderId)
+    {
+        case GIMPROVIDERID_HYPERV:
+            return GIMHvWriteMsr(pVCpu, idMsr, pRange, uValue, uRawValue);
+
+        default:
+            AssertMsgFailed(("GIMWriteMsr: for unknown provider %u idMsr=%#RX32 -> #GP(0)", pVM->gim.s.enmProviderId, idMsr));
+            return VERR_CPUM_RAISE_GP_0;
+    }
+}
+
Index: trunk/src/VBox/VMM/VMMAll/GIMAllHv.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/GIMAllHv.cpp	(revision 51332)
+++ trunk/src/VBox/VMM/VMMAll/GIMAllHv.cpp	(revision 51333)
@@ -30,2 +30,14 @@
 }
 
+
+DECLEXPORT(int) GIMHvReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    return VINF_SUCCESS;
+}
+
+
+DECLEXPORT(int) GIMHvWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
+{
+    return VINF_SUCCESS;
+}
+
Index: trunk/src/VBox/VMM/VMMR3/GIM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/GIM.cpp	(revision 51332)
+++ trunk/src/VBox/VMM/VMMR3/GIM.cpp	(revision 51333)
@@ -28,6 +28,6 @@
  * A GIM provider implements a particular hypervisor interface such as Microsoft
  * Hyper-V, Linux KVM and so on. It hooks into various components in the VMM to
- * ease the guest in running under a recognized virtualized environment. This is
- * also referred to as paravirtualization interfaces.
+ * ease the guest in running under a recognized, virtualized environment. This
+ * is also referred to as paravirtualization interfaces.
  *
  * The idea behind this is primarily for making guests more accurate and
@@ -39,5 +39,6 @@
  * itself, resulting in higher accuracy and saving several CPU cycles.
  *
- * Only one provider can be active for a running VM.
+ * At most, only one GIM provider can be active for a running VM and cannot be
+ * changed during the lifetime of the VM.
  */
 
@@ -105,24 +106,32 @@
     AssertLogRelRCReturn(rc, rc);
 
+    /** @cfgm{GIM/Version, uint32_t}
+     * The interface version. The default is 0, which means "provide the most
+     * up-to-date implementation". */
+    uint32_t uVersion;
+    rc = CFGMR3QueryU32Def(pCfgNode, "Version", &uVersion, 0 /* default */);
+    AssertLogRelRCReturn(rc, rc);
+
     /*
      * Setup the GIM provider for this VM.
      */
-    LogRel(("GIM: Using provider \"%s\"\n", szProvider));
+    LogRel(("GIM: Using provider \"%s\" version %u\n", szProvider, uVersion));
     if (!RTStrCmp(szProvider, "None"))
     {
         Assert(!pVM->gim.s.fEnabled);
-        pVM->gim.s.enmProvider = GIMPROVIDER_NONE;
+        pVM->gim.s.enmProviderId = GIMPROVIDERID_NONE;
     }
     else
     {
         pVM->gim.s.fEnabled = true;
+        pVM->gim.s.u32Version = uVersion;
         if (!RTStrCmp(szProvider, "Minimal"))
         {
-            pVM->gim.s.enmProvider = GIMPROVIDER_MINIMAL;
+            pVM->gim.s.enmProviderId = GIMPROVIDERID_MINIMAL;
             rc = GIMR3MinimalInit(pVM);
         }
         else if (!RTStrCmp(szProvider, "HyperV"))
         {
-            pVM->gim.s.enmProvider = GIMPROVIDER_HYPERV;
+            pVM->gim.s.enmProviderId = GIMPROVIDERID_HYPERV;
             rc = GIMR3HvInit(pVM);
         }
@@ -157,7 +166,7 @@
     }
 
-    switch (pVM->gim.s.enmProvider)
-    {
-        case GIMPROVIDER_MINIMAL:
+    switch (pVM->gim.s.enmProviderId)
+    {
+        case GIMPROVIDERID_MINIMAL:
         {
             GIMR3MinimalRelocate(pVM, offDelta);
@@ -165,5 +174,5 @@
         }
 
-        case GIMPROVIDER_HYPERV:
+        case GIMPROVIDERID_HYPERV:
         {
             GIMR3HvRelocate(pVM, offDelta);
@@ -171,8 +180,8 @@
         }
 
-        case GIMPROVIDER_KVM:            /** @todo KVM. */
+        case GIMPROVIDERID_KVM:            /** @todo KVM. */
         default:
         {
-            AssertMsgFailed(("Invalid provider id %#x\n", pVM->gim.s.enmProvider));
+            AssertMsgFailed(("Invalid provider Id %#x\n", pVM->gim.s.enmProviderId));
             break;
         }
Index: trunk/src/VBox/VMM/VMMR3/GIMHv.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/GIMHv.cpp	(revision 51332)
+++ trunk/src/VBox/VMM/VMMR3/GIMHv.cpp	(revision 51333)
@@ -25,4 +25,5 @@
 #include <iprt/assert.h>
 #include <iprt/err.h>
+#include <iprt/string.h>
 
 #include <VBox/vmm/cpum.h>
@@ -30,4 +31,5 @@
 #include <VBox/vmm/hm.h>
 #include <VBox/vmm/pdmapi.h>
+#include <VBox/version.h>
 
 /*******************************************************************************
@@ -37,10 +39,18 @@
 
 
+/**
+ * Initializes the Hyper-V GIM provider.
+ *
+ * @returns VBox status code.
+ * @param   pVM         Pointer to the VM.
+ * @param   uVersion    The interface version this VM should use.
+ */
 VMMR3_INT_DECL(int) GIMR3HvInit(PVM pVM)
 {
     AssertReturn(pVM, VERR_INVALID_PARAMETER);
-    AssertReturn(pVM->gim.s.enmProvider == GIMPROVIDER_HYPERV, VERR_INTERNAL_ERROR_5);
+    AssertReturn(pVM->gim.s.enmProviderId == GIMPROVIDERID_HYPERV, VERR_INTERNAL_ERROR_5);
 
     int rc;
+#if 0
     pVM->gim.s.pfnHypercallR3 = &GIMHvHypercall;
     if (!HMIsEnabled(pVM))
@@ -51,4 +61,21 @@
     rc = PDMR3LdrGetSymbolR0(pVM, NULL /* pszModule */, GIMHV_HYPERCALL, &pVM->gim.s.pfnHypercallR0);
     AssertRCReturn(rc, rc);
+#endif
+
+    /*
+     * Determine interface capabilities based on the version.
+     */
+    uint32_t uBaseFeat    = 0;
+    uint32_t uPartFlags   = 0;
+    uint32_t uPowMgmtFeat = 0;
+    uint32_t uMiscFeat    = 0;
+    uint32_t uHyperHints  = 0;
+    if (!pVM->gim.s.u32Version)
+    {
+        uBaseFeat = GIM_HV_BASE_FEAT_PART_REF_COUNT_MSR;
+        pVM->gim.s.u.hv.u16HyperIdVersionMajor = VBOX_VERSION_MAJOR;
+        pVM->gim.s.u.hv.u16HyperIdVersionMajor = VBOX_VERSION_MINOR;
+        pVM->gim.s.u.hv.u32HyperIdBuildNumber  = VBOX_VERSION_BUILD;
+    }
 
     /*
@@ -57,5 +84,58 @@
     CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_HVP);
 
-    /** @todo Register CPUID leaves, MSR ranges with CPUM. */
+    /*
+     * Modify the standard hypervisor leaves for Hyper-V.
+     */
+    CPUMCPUIDLEAF HyperLeaf;
+    RT_ZERO(HyperLeaf);
+    HyperLeaf.uLeaf        = UINT32_C(0x40000000);
+    HyperLeaf.uEax         = UINT32_C(0x40000005); /* Minimum value for Hyper-V */
+    HyperLeaf.uEbx         = 0x7263694D;           /* 'Micr' */
+    HyperLeaf.uEcx         = 0x666F736F;           /* 'osof' */
+    HyperLeaf.uEdx         = 0x76482074;           /* 't Hv' */
+    rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf);
+    AssertLogRelRCReturn(rc, rc);
+
+    HyperLeaf.uLeaf        = UINT32_C(0x40000001);
+    HyperLeaf.uEax         = 0x31237648;           /* 'Hv#1' */
+    HyperLeaf.uEbx         = 0;                    /* Reserved */
+    HyperLeaf.uEcx         = 0;                    /* Reserved */
+    HyperLeaf.uEdx         = 0;                    /* Reserved */
+    rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf);
+    AssertLogRelRCReturn(rc, rc);
+
+    /*
+     * Add Hyper-V specific leaves.
+     */
+    HyperLeaf.uLeaf        = UINT32_C(0x40000002); /* MBZ until MSR_HV_GUEST_OS_ID is set by the guest. */
+    HyperLeaf.uEax         = 0;
+    HyperLeaf.uEbx         = 0;
+    HyperLeaf.uEcx         = 0;
+    HyperLeaf.uEdx         = 0;
+    rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf);
+    AssertLogRelRCReturn(rc, rc);
+
+    HyperLeaf.uLeaf        = UINT32_C(0x40000003);
+    HyperLeaf.uEax         = uBaseFeat;
+    HyperLeaf.uEbx         = uPartFlags;
+    HyperLeaf.uEcx         = uPowMgmtFeat;
+    HyperLeaf.uEdx         = uMiscFeat;
+    rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf);
+    AssertLogRelRCReturn(rc, rc);
+
+    /*
+     * Register the complete MSR range for Hyper-V.
+     */
+    CPUMMSRRANGE MsrRange;
+    RT_ZERO(MsrRange);
+    MsrRange.uFirst     = UINT32_C(0x40000000);
+    MsrRange.uLast      = UINT32_C(0x40000105);
+    MsrRange.enmRdFn    = kCpumMsrRdFn_Gim;
+    MsrRange.enmWrFn    = kCpumMsrWrFn_Gim;
+    RTStrCopy(MsrRange.szName, sizeof(MsrRange.szName), "Hyper-V");
+    rc = CPUMR3MsrRangesInsert(pVM, &MsrRange);
+    AssertLogRelRCReturn(rc, rc);
+
+
     return VINF_SUCCESS;
 }
@@ -64,6 +144,6 @@
 VMMR3_INT_DECL(void) GIMR3HvRelocate(PVM pVM, RTGCINTPTR offDelta)
 {
-    int rc = PDMR3LdrGetSymbolRC(pVM, NULL /* pszModule */, GIMHV_HYPERCALL, &pVM->gim.s.pfnHypercallRC);
-    AssertFatalRC(rc);
+//    int rc = PDMR3LdrGetSymbolRC(pVM, NULL /* pszModule */, GIMHV_HYPERCALL, &pVM->gim.s.pfnHypercallRC);
+//    AssertFatalRC(rc);
 }
 
Index: trunk/src/VBox/VMM/VMMR3/GIMMinimal.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/GIMMinimal.cpp	(revision 51332)
+++ trunk/src/VBox/VMM/VMMR3/GIMMinimal.cpp	(revision 51333)
@@ -36,5 +36,5 @@
 {
     AssertReturn(pVM, VERR_INVALID_PARAMETER);
-    AssertReturn(pVM->gim.s.enmProvider == GIMPROVIDER_MINIMAL, VERR_INTERNAL_ERROR_5);
+    AssertReturn(pVM->gim.s.enmProviderId == GIMPROVIDERID_MINIMAL, VERR_INTERNAL_ERROR_5);
 
     Assert(CPUMGetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_HVP));
Index: trunk/src/VBox/VMM/include/GIMHvInternal.h
===================================================================
--- trunk/src/VBox/VMM/include/GIMHvInternal.h	(revision 51332)
+++ trunk/src/VBox/VMM/include/GIMHvInternal.h	(revision 51333)
@@ -21,13 +21,312 @@
 #include <iprt/cdefs.h>
 #include <VBox/types.h>
+#include <VBox/vmm/cpum.h>
+
+/** @name Hyper-V base feature identification.
+ * Base features based on current partition privileges.
+ * @{
+ */
+/** Virtual processor runtime MSR available. */
+#define GIM_HV_BASE_FEAT_VP_RUNTIME_MSR           RT_BIT(0)
+/** Partition reference counter MSR available. */
+#define GIM_HV_BASE_FEAT_PART_REF_COUNT_MSR       RT_BIT(1)
+/** Basic Synthetic Interrupt Controller MSRs available. */
+#define GIM_HV_BASE_FEAT_BASIC_SYNTH_IC           RT_BIT(2)
+/** Synthetic Timer MSRs available. */
+#define GIM_HV_BASE_FEAT_SYNTH_TIMER_MSRS         RT_BIT(3)
+/** APIC access MSRs (EOI, ICR, TPR) available. */
+#define GIM_HV_BASE_FEAT_APIC_ACCESS_MSRS         RT_BIT(4)
+/** Hypercall MSRs available. */
+#define GIM_HV_BASE_FEAT_HYPERCALL_MSRS           RT_BIT(5)
+/** Access to VCPU index MSR available. */
+#define GIM_HV_BASE_FEAT_VP_ID_MSR                RT_BIT(6)
+/** Virtual system reset MSR available. */
+#define GIM_HV_BASE_FEAT_VIRT_SYS_RESET_MSR       RT_BIT(7)
+/** Statistic pages MSRs available. */
+#define GIM_HV_BASE_FEAT_STAT_PAGES_MSR           RT_BIT(8)
+/** Paritition reference TSC MSR available. */
+#define GIM_HV_BASE_FEAT_PART_REF_TSC_MSR         RT_BIT(9)
+/** Virtual guest idle state MSR available. */
+#define GIM_HV_BASE_FEAT_GUEST_IDLE_STATE_MSR     RT_BIT(10)
+/** Timer frequency MSRs available. */
+#define GIM_HV_BASE_FEAT_TIMER_FREQ_MSRS          RT_BIT(11)
+/** Debug MSRs available. */
+#define GIM_HV_BASE_FEAT_DEBUG_MSRS               RT_BIT(12)
+/** @}  */
+
+/** @name Hyper-V partition-creation feature identification.
+ * Indicates flags specified during partition creation.
+ * @{
+ */
+/** Create partitions. */
+#define GIM_HV_PART_FLAGS_CREATE_PART             RT_BIT(0)
+/** Access partition Id. */
+#define GIM_HV_PART_FLAGS_ACCESS_PART_ID          RT_BIT(1)
+/** Access memory pool. */
+#define GIM_HV_PART_FLAGS_ACCESS_MEMORY_POOL      RT_BIT(2)
+/** Adjust message buffers. */
+#define GIM_HV_PART_FLAGS_ADJUST_MSG_BUFFERS      RT_BIT(3)
+/** Post messages. */
+#define GIM_HV_PART_FLAGS_POST_MSGS               RT_BIT(4)
+/** Signal events. */
+#define GIM_HV_PART_FLAGS_SIGNAL_EVENTS           RT_BIT(5)
+/** Create port. */
+#define GIM_HV_PART_FLAGS_CREATE_PORT             RT_BIT(6)
+/** Connect port. */
+#define GIM_HV_PART_FLAGS_CONNECT_PORT            RT_BIT(7)
+/** Access statistics. */
+#define GIM_HV_PART_FLAGS_ACCESS_STATS            RT_BIT(8)
+/** Debugging.*/
+#define GIM_HV_PART_FLAGS_DEBUGGING               RT_BIT(11)
+/** CPU management. */
+#define GIM_HV_PART_FLAGS_CPU_MGMT                RT_BIT(12)
+/** CPU profiler. */
+#define GIM_HV_PART_FLAGS_CPU_PROFILER            RT_BIT(13)
+/** Enable expanded stack walking. */
+#define GIM_HV_PART_FLAGS_EXPANDED_STACK_WALK     RT_BIT(14)
+/** @}  */
+
+/** @name Hyper-V power management feature identification.
+ * @{
+ */
+/** Maximum CPU power state C0. */
+#define GIM_HV_PM_MAX_CPU_POWER_STATE_C0          RT_BIT(0)
+/** Maximum CPU power state C1. */
+#define GIM_HV_PM_MAX_CPU_POWER_STATE_C1          RT_BIT(1)
+/** Maximum CPU power state C2. */
+#define GIM_HV_PM_MAX_CPU_POWER_STATE_C2          RT_BIT(2)
+/** Maximum CPU power state C3. */
+#define GIM_HV_PM_MAX_CPU_POWER_STATE_C3          RT_BIT(3)
+/** HPET is required to enter C3 power state. */
+#define GIM_HV_PM_HPET_REQD_FOR_C3                RT_BIT(4)
+/** @}  */
+
+/** @name Hyper-V miscellaneous feature identification.
+ * Miscellaneous features available for the current partition.
+ * @{
+ */
+/** MWAIT instruction available. */
+#define GIM_HV_MISC_FEAT_MWAIT                    RT_BIT(0)
+/** Guest debugging support available. */
+#define GIM_HV_MISC_FEAT_GUEST_DEBUGGING          RT_BIT(1)
+/** Performance monitor support is available. */
+#define GIM_HV_MISC_FEAT_PERF_MON                 RT_BIT(2)
+/** Support for physical CPU dynamic partitioning events. */
+#define GIM_HV_MISC_FEAT_PCPU_DYN_PART_EVENT      RT_BIT(3)
+/** Support for passing hypercall input parameter block via XMM registers. */
+#define GIM_HV_MISC_FEAT_XMM_HYPERCALL_INPUT      RT_BIT(4)
+/** Support for virtual guest idle state. */
+#define GIM_HV_MISC_FEAT_GUEST_IDLE_STATE         RT_BIT(5)
+/** Support for hypervisor sleep state. */
+#define GIM_HV_MISC_FEAT_HYPERVISOR_SLEEP_STATE   RT_BIT(6)
+/** Support for querying NUMA distances. */
+#define GIM_HV_MISC_FEAT_QUERY_NUMA_DISTANCE      RT_BIT(7)
+/** Support for determining timer frequencies. */
+#define GIM_HV_MISC_FEAT_TIMER_FREQ               RT_BIT(8)
+/** Support for injecting synthetic machine checks. */
+#define GIM_HV_MISC_FEAT_INJECT_SYNTH_MC_XCPT     RT_BIT(9)
+/** Support for guest crash MSRs. */
+#define GIM_HV_MISC_FEAT_GUEST_CRASH_MSRS         RT_BIT(10)
+/** Support for debug MSRs. */
+#define GIM_HV_MISC_FEAT_DEBUG_MSRS               RT_BIT(11)
+/** Npiep1 Available */ /** @todo What the heck is this? */
+#define GIM_HV_MISC_FEAT_NPIEP1                   RT_BIT(12)
+/** Disable hypervisor available. */
+#define GIM_HV_MISC_FEAT_DISABLE_HYPERVISOR       RT_BIT(13)
+/** @}  */
+
+/** @name Hyper-V implementation recommendations.
+ * Recommendations from the hypervisor for the guest for optimal performance.
+ * @{
+ */
+/** Use hypercall for address space switches rather than MOV CR3. */
+#define GIM_HV_HINT_HYPERCALL_FOR_PROCESS_SWITCH  RT_BIT(0)
+/** Use hypercall for local TLB flushes rather than INVLPG/MOV CR3. */
+#define GIM_HV_HINT_HYPERCALL_FOR_TLB_FLUSH       RT_BIT(1)
+/** Use hypercall for inter-CPU TLB flushes rather than IPIs. */
+#define GIM_HV_HINT_HYPERCALL_FOR_TLB_SHOOTDOWN   RT_BIT(2)
+/** Use MSRs for APIC access (EOI, ICR, TPR) rather than MMIO. */
+#define GIM_HV_HINT_MSR_FOR_APIC_ACCESS           RT_BIT(3)
+/** Use hypervisor provided MSR for a system reset. */
+#define GIM_HV_HINT_MSR_FOR_SYS_RESET             RT_BIT(4)
+/** Relax timer-related checks (watchdogs/deadman timeouts) that rely on
+ *  timely deliver of external interrupts. */
+#define GIM_HV_HINT_RELAX_TIME_CHECKS             RT_BIT(5)
+/** Use DMA remapping. */
+#define GIM_HV_HINT_DMA_REMAPPING                 RT_BIT(6)
+/** Use interrupt remapping. */
+#define GIM_HV_HINT_INTERRUPT_REMAPPING           RT_BIT(7)
+/** Use X2APIC MSRs rather than MMIO. */
+#define GIM_HV_HINT_X2APIC_MSRS                   RT_BIT(8)
+/** Deprecate Auto EOI (end of interrupt). */
+#define GIM_HV_HINT_DEPRECATE_AUTO_EOI            RT_BIT(9)
+/** @}  */
+
+
+/** @name Hyper-V implementation hardware features.
+ * Which hardware features are in use by the hypervisor.
+ * @{
+ */
+/** APIC overlay is used. */
+#define GIM_HV_HOST_FEAT_AVIC                     RT_BIT(0)
+/** MSR bitmaps is used. */
+#define GIM_HV_HOST_FEAT_MSR_BITMAP               RT_BIT(1)
+/** Architectural performance counter supported. */
+#define GIM_HV_HOST_FEAT_PERF_COUNTER             RT_BIT(2)
+/** Nested paging is used. */
+#define GIM_HV_HOST_FEAT_NESTED_PAGING            RT_BIT(3)
+/** DMA remapping is used. */
+#define GIM_HV_HOST_FEAT_DMA_REMAPPING            RT_BIT(4)
+/** Interrupt remapping is used. */
+#define GIM_HV_HOST_FEAT_INTERRUPT_REMAPPING      RT_BIT(5)
+/** Memory patrol scrubber is present. */
+#define GIM_HV_HOST_FEAT_MEM_PATROL_SCRUBBER      RT_BIT(6)
+/** @}  */
+
+
+/** @name Hyper-V MSRs.
+ * @{
+ */
+/** Guest OS identification (R/W) */
+#define MSR_GIM_HV_GUEST_OS_ID                    UINT32_C(0x40000000)
+/** Enable hypercall interface (R/W) */
+#define MSR_GIM_HV_HYPERCALL                      UINT32_C(0x40000001)
+/** Virtual processor's (VCPU) index (R) */
+#define MSR_GIM_HV_VP_INDEX                       UINT32_C(0x40000002)
+/** Reset operation (R/W) */
+#define MSR_GIM_HV_RESET                          UINT32_C(0x40000003)
+/** Virtual processor's (VCPU) runtime (R) */
+#define MSR_GIM_HV_VP_RUNTIME                     UINT32_C(0x40000010)
+/** Per-VM reference counter (R) */
+#define MSR_GIM_HV_TIME_REF_COUNT                 UINT32_C(0x40000020)
+/** Per-VM TSC (R) */
+#define MSR_GIM_HV_REF_TSC                        UINT32_C(0x40000021)
+/** Frequency of TSC in Hz as reported by the hypervisor (R) */
+#define MSR_GIM_HV_TSC_FREQ                       UINT32_C(0x40000022)
+/** Frequency of LAPIC in Hz as reported by the hypervisor (R) */
+#define MSR_GIM_HV_APIC_FREQ                      UINT32_C(0x40000023)
+/** Access to APIC EOI (End-Of-Interrupt) register (W) */
+#define MSR_GIM_HV_EOI                            UINT32_C(0x40000070)
+/** Access to APIC ICR (Interrupt Command) register (R/W) */
+#define MSR_GIM_HV_ICR                            UINT32_C(0x40000071)
+/** Access to APIC TPR (Task Priority) register (R/W) */
+#define MSR_GIM_HV_TPR                            UINT32_C(0x40000072)
+/** Enables lazy EOI processing (R/W) */
+#define MSR_GIM_HV_APIC_ASSIST_PAGE               UINT32_C(0x40000073)
+/** Control behaviour of synthetic interrupt controller (R/W) */
+#define MSR_GIM_HV_SCONTROL                       UINT32_C(0x40000080)
+/** Synthetic interrupt controller version (R) */
+#define MSR_GIM_HV_SVERSION                       UINT32_C(0x40000081)
+/** Base address of synthetic interrupt event flag (R/W) */
+#define MSR_GIM_HV_SIEFP                          UINT32_C(0x40000082)
+/** Base address of synthetic interrupt parameter page (R/W) */
+#define MSR_GIM_HV_SIMP                           UINT32_C(0x40000083)
+/** End-Of-Message in synthetic interrupt parameter page (W) */
+#define MSR_GIM_HV_EOM                            UINT32_C(0x40000084)
+/** Configures synthetic interrupt source 0 (R/W) */
+#define MSR_GIM_HV_SINT0                          UINT32_C(0x40000090)
+/** Configures synthetic interrupt source 1 (R/W) */
+#define MSR_GIM_HV_SINT1                          UINT32_C(0x40000091)
+/** Configures synthetic interrupt source 2 (R/W) */
+#define MSR_GIM_HV_SINT2                          UINT32_C(0x40000092)
+/** Configures synthetic interrupt source 3 (R/W) */
+#define MSR_GIM_HV_SINT3                          UINT32_C(0x40000093)
+/** Configures synthetic interrupt source 4 (R/W) */
+#define MSR_GIM_HV_SINT4                          UINT32_C(0x40000094)
+/** Configures synthetic interrupt source 5 (R/W) */
+#define MSR_GIM_HV_SINT5                          UINT32_C(0x40000095)
+/** Configures synthetic interrupt source 6 (R/W) */
+#define MSR_GIM_HV_SINT6                          UINT32_C(0x40000096)
+/** Configures synthetic interrupt source 7 (R/W) */
+#define MSR_GIM_HV_SINT7                          UINT32_C(0x40000097)
+/** Configures synthetic interrupt source 8 (R/W) */
+#define MSR_GIM_HV_SINT8                          UINT32_C(0x40000098)
+/** Configures synthetic interrupt source 9 (R/W) */
+#define MSR_GIM_HV_SINT9                          UINT32_C(0x40000099)
+/** Configures synthetic interrupt source 10 (R/W) */
+#define MSR_GIM_HV_SINT10                         UINT32_C(0x4000009A)
+/** Configures synthetic interrupt source 11 (R/W) */
+#define MSR_GIM_HV_SINT11                         UINT32_C(0x4000009B)
+/** Configures synthetic interrupt source 12 (R/W) */
+#define MSR_GIM_HV_SINT12                         UINT32_C(0x4000009C)
+/** Configures synthetic interrupt source 13 (R/W) */
+#define MSR_GIM_HV_SINT13                         UINT32_C(0x4000009D)
+/** Configures synthetic interrupt source 14 (R/W) */
+#define MSR_GIM_HV_SINT14                         UINT32_C(0x4000009E)
+/** Configures synthetic interrupt source 15 (R/W) */
+#define MSR_GIM_HV_SINT15                         UINT32_C(0x4000009F)
+/** Configures register for synthetic timer 0 (R/W) */
+#define MSR_GIM_HV_STIMER0_CONFIG                 UINT32_C(0x400000B0)
+/** Expiration time or period for synthetic timer 0 (R/W) */
+#define MSR_GIM_HV_STIMER0_COUNT                  UINT32_C(0x400000B1)
+/** Configures register for synthetic timer 1 (R/W) */
+#define MSR_GIM_HV_STIMER1_CONFIG                 UINT32_C(0x400000B2)
+/** Expiration time or period for synthetic timer 1 (R/W) */
+#define MSR_GIM_HV_STIMER1_COUNT                  UINT32_C(0x400000B3)
+/** Configures register for synthetic timer 2 (R/W) */
+#define MSR_GIM_HV_STIMER2_CONFIG                 UINT32_C(0x400000B4)
+/** Expiration time or period for synthetic timer 2 (R/W) */
+#define MSR_GIM_HV_STIMER2_COUNT                  UINT32_C(0x400000B5)
+/** Configures register for synthetic timer 3 (R/W) */
+#define MSR_GIM_HV_STIMER3_CONFIG                 UINT32_C(0x400000B6)
+/** Expiration time or period for synthetic timer 3 (R/W) */
+#define MSR_GIM_HV_STIMER3_COUNT                  UINT32_C(0x400000B7)
+/** Trigger to transition to power state C1 (R) */
+#define MSR_GIM_HV_POWER_STATE_TRIGGER_C1         UINT32_C(0x400000C1)
+/** Trigger to transition to power state C2 (R) */
+#define MSR_GIM_HV_POWER_STATE_TRIGGER_C2         UINT32_C(0x400000C2)
+/** Trigger to transition to power state C3 (R) */
+#define MSR_GIM_HV_POWER_STATE_TRIGGER_C3         UINT32_C(0x400000C3)
+/** Configure the recipe for power state transitions to C1 (R/W) */
+#define MSR_GIM_HV_POWER_STATE_CONFIG_C1          UINT32_C(0x400000D1)
+/** Configure the recipe for power state transitions to C2 (R/W) */
+#define MSR_GIM_HV_POWER_STATE_CONFIG_C2          UINT32_C(0x400000D2)
+/** Configure the recipe for power state transitions to C3 (R/W) */
+#define MSR_GIM_HV_POWER_STATE_CONFIG_C3          UINT32_C(0x400000D3)
+/** Map the guest's retail partition stats page (R/W) */
+#define MSR_GIM_HV_STATS_PART_RETAIL_PAGE         UINT32_C(0x400000E0)
+/** Map the guest's internal partition stats page (R/W) */
+#define MSR_GIM_HV_STATS_PART_INTERNAL_PAGE       UINT32_C(0x400000E1)
+/** Map the guest's retail VP stats page (R/W) */
+#define MSR_GIM_HV_STATS_VP_RETAIL_PAGE           UINT32_C(0x400000E2)
+/** Map the guest's internal VP stats page (R/W) */
+#define MSR_GIM_HV_STATS_VP_INTERNAL_PAGE         UINT32_C(0x400000E3)
+/** Trigger the guest's transition to idle power state (R) */
+#define MSR_GIM_HV_GUEST_IDLE                     UINT32_C(0x400000F0)
+/** Synthetic debug control. */
+#define MSR_GIM_HV_SYNTH_DEBUG_CONTROL            UINT32_C(0x400000F1)
+/** Synthetic debug status. */
+#define MSR_GIM_HV_SYNTH_DEBUG_STATUS             UINT32_C(0x400000F2)
+/** Synthetic debug send buffer. */
+#define MSR_GIM_HV_SYNTH_DEBUG_SEND_BUFFER        UINT32_C(0x400000F3)
+/** Synthetic debug receive buffer. */
+#define MSR_GIM_HV_SYNTH_DEBUG_RECEIVE_BUFFER     UINT32_C(0x400000F4)
+/** Synthetic debug pending buffer. */
+#define MSR_GIM_HV_SYNTH_DEBUG_PENDING_BUFFER     UINT32_C(0x400000F5)
+/** Guest crash MSR 0. */
+#define MSR_GIM_HV_CRASH_P0                       UINT32_C(0x40000100)
+/** Guest crash MSR 1. */
+#define MSR_GIM_HV_CRASH_P1                       UINT32_C(0x40000101)
+/** Guest crash MSR 2. */
+#define MSR_GIM_HV_CRASH_P2                       UINT32_C(0x40000102)
+/** Guest crash MSR 3. */
+#define MSR_GIM_HV_CRASH_P3                       UINT32_C(0x40000103)
+/** Guest crash MSR 4. */
+#define MSR_GIM_HV_CRASH_P4                       UINT32_C(0x40000104)
+/** Guest crash control. */
+#define MSR_GIM_HV_CRASH_CTL                      UINT32_C(0x40000105)
+/** @} */
+
 
 RT_C_DECLS_BEGIN
 
 #ifdef IN_RING3
-VMMR3_INT_DECL(int)         GIMR3HvInit(PVM pVM);
-VMMR3_INT_DECL(void)        GIMR3HvRelocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3_INT_DECL(int)     GIMR3HvInit(PVM pVM);
+VMMR3_INT_DECL(void)    GIMR3HvRelocate(PVM pVM, RTGCINTPTR offDelta);
 #endif /* IN_RING3 */
 
-DECLEXPORT(int)             GIMHvHypercall(PVMCPU pVCpu, PCPUMCTX pCtx);
+VMMDECL(int)            GIMHvHypercall(PVMCPU pVCpu, PCPUMCTX pCtx);
+VMMDECL(int)            GIMHvReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue);
+VMMDECL(int)            GIMHvWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue);
 
 RT_C_DECLS_END
Index: trunk/src/VBox/VMM/include/GIMInternal.h
===================================================================
--- trunk/src/VBox/VMM/include/GIMInternal.h	(revision 51332)
+++ trunk/src/VBox/VMM/include/GIMInternal.h	(revision 51333)
@@ -21,7 +21,4 @@
 #include <VBox/vmm/gim.h>
 
-#define GIM_SSM_VERSION                 1
-
-
 RT_C_DECLS_BEGIN
 
@@ -41,5 +38,9 @@
     bool                             fEnabled;
     /** The provider that is active for this VM. */
-    GIMPROVIDER                      enmProvider;
+    GIMPROVIDERID                    enmProviderId;
+    /** The interface version. */
+    uint32_t                         u32Version;
+
+#if 0
     /** Pointer to the provider's ring-3 hypercall handler. */
     R3PTRTYPE(PFNGIMHYPERCALL)       pfnHypercallR3;
@@ -48,4 +49,19 @@
     /** Pointer to the provider's raw-mode context hypercall handler. */
     RCPTRTYPE(PFNGIMHYPERCALL)       pfnHypercallRC;
+
+    /** Pointer to the provider's ring-3 MSR-read handler. */
+    R3PTRTYPE(PFNGIMRDMSR)           pfnReadMsrR3;
+    /** Pointer to the provider's ring-0 MSR-read handler. */
+    R0PTRTYPE(PFNGIMRDMSR)           pfnReadMsrR0;
+    /** Pointer to the provider's raw-mode context MSR-read handler. */
+    RCPTRTYPE(PFNGIMRDMSR)           pfnReadMsrRC;
+
+    /** Pointer to the provider's ring-3 MSR-read handler. */
+    R3PTRTYPE(PFNGIMWDMSR)           pfnWriteMsrR3;
+    /** Pointer to the provider's ring-0 MSR-read handler. */
+    R0PTRTYPE(PFNGIMWDMSR)           pfnWriteMsrRR0;
+    /** Pointer to the provider's raw-mode context MSR-read handler. */
+    RCPTRTYPE(PFNGIMWDMSR)           pfnWriteMsrRRC;
+#endif
 
     union
@@ -58,10 +74,10 @@
         {
             /** Hypervisor system identity - Minor version number. */
-            uint16_t                 uVersionMinor;
+            uint16_t                 u16HyperIdVersionMinor;
             /** Hypervisor system identity - Major version number. */
-            uint16_t                 uVersionMajor;
-            /** Hypervisor system identify - Service branch (Bits 31-24) and number (Bits
-             *  23-0). */
-            uint32_t                 uVersionService;
+            uint16_t                 u16HyperIdVersionMajor;
+            /** Hypervisor system identify - Build number. */
+            uint32_t                 u32HyperIdBuildNumber;
+
             /** Guest OS identity MSR. */
             uint64_t                 u64GuestOsIdMsr;
