Index: /trunk/src/VBox/VMM/Makefile.kmk
===================================================================
--- /trunk/src/VBox/VMM/Makefile.kmk	(revision 54818)
+++ /trunk/src/VBox/VMM/Makefile.kmk	(revision 54819)
@@ -151,4 +151,5 @@
 	VMMR3/GIM.cpp \
 	VMMR3/GIMHv.cpp \
+	VMMR3/GIMKvm.cpp \
 	VMMR3/GIMMinimal.cpp \
 	VMMR3/IEMR3.cpp \
@@ -230,4 +231,5 @@
 	VMMAll/GIMAll.cpp \
 	VMMAll/GIMAllHv.cpp \
+	VMMAll/GIMAllKvm.cpp \
 	VMMAll/TMAll.cpp \
 	VMMAll/TMAllCpu.cpp \
@@ -456,23 +458,24 @@
  	VMMRC/VMMRCA.asm \
  	$(if-expr defined(VBOX_WITH_RAW_MODE), \
-	VMMRC/CSAMRC.cpp \
+ 	VMMRC/CSAMRC.cpp \
  	VMMRC/PATMRC.cpp \
-	,) \
+ 	,) \
  	VMMRZ/DBGFRZ.cpp \
  	VMMRZ/PGMRZDynMap.cpp \
  	VMMRZ/VMMRZ.cpp \
  	VMMAll/CPUMAllRegs.cpp \
-	VMMAll/CPUMAllMsrs.cpp \
+ 	VMMAll/CPUMAllMsrs.cpp \
  	VMMAll/DBGFAll.cpp \
-	VMMAll/IEMAll.cpp \
-	VMMAll/IEMAllAImpl.asm \
-	VMMAll/IEMAllAImplC.cpp \
-  	VMMAll/IOMAll.cpp \
+ 	VMMAll/IEMAll.cpp \
+ 	VMMAll/IEMAllAImpl.asm \
+ 	VMMAll/IEMAllAImplC.cpp \
+ 	VMMAll/IOMAll.cpp \
  	VMMAll/IOMAllMMIO.cpp \
  	VMMAll/EMAll.cpp \
  	VMMAll/EMAllA.asm \
-	VMMAll/FTMAll.cpp \
-	VMMAll/GIMAll.cpp \
-	VMMAll/GIMAllHv.cpp \
+ 	VMMAll/FTMAll.cpp \
+ 	VMMAll/GIMAll.cpp \
+ 	VMMAll/GIMAllHv.cpp \
+ 	VMMAll/GIMAllKvm.cpp \
  	VMMAll/MMAll.cpp \
  	VMMAll/MMAllHyper.cpp \
@@ -498,5 +501,5 @@
  	VMMAll/VMMAllA.asm \
  	$(if-expr defined(VBOX_WITH_RAW_MODE), \
-	VMMAll/CSAMAll.cpp \
+ 	VMMAll/CSAMAll.cpp \
  	VMMAll/PATMAll.cpp \
        ,)
@@ -552,12 +555,12 @@
  	VMMR0/CPUMR0.cpp \
  	VMMR0/CPUMR0A.asm \
-	VMMR0/GIMR0.cpp \
-	VMMR0/GIMR0Hv.cpp \
+ 	VMMR0/GIMR0.cpp \
+ 	VMMR0/GIMR0Hv.cpp \
  	VMMR0/GMMR0.cpp \
  	VMMR0/GVMMR0.cpp \
  	VMMR0/HMR0.cpp \
  	VMMR0/HMR0A.asm \
-	VMMR0/HMVMXR0.cpp \
-	VMMR0/HMSVMR0.cpp \
+ 	VMMR0/HMVMXR0.cpp \
+ 	VMMR0/HMSVMR0.cpp \
  	VMMR0/PDMR0Device.cpp \
  	VMMR0/PDMR0Driver.cpp \
@@ -570,5 +573,5 @@
  	VMMRZ/VMMRZ.cpp \
  	VMMAll/CPUMAllRegs.cpp \
-	VMMAll/CPUMAllMsrs.cpp \
+ 	VMMAll/CPUMAllMsrs.cpp \
  	VMMAll/CPUMStack.cpp \
  	VMMAll/DBGFAll.cpp \
@@ -576,10 +579,11 @@
  	VMMAll/EMAllA.asm \
  	VMMAll/FTMAll.cpp \
-	VMMAll/GIMAll.cpp \
-	VMMAll/GIMAllHv.cpp \
+ 	VMMAll/GIMAll.cpp \
+ 	VMMAll/GIMAllHv.cpp \
+ 	VMMAll/GIMAllKvm.cpp \
  	VMMAll/HMAll.cpp \
-	VMMAll/IEMAll.cpp \
-	VMMAll/IEMAllAImpl.asm \
-	VMMAll/IEMAllAImplC.cpp \
+ 	VMMAll/IEMAll.cpp \
+ 	VMMAll/IEMAllAImpl.asm \
+ 	VMMAll/IEMAllAImplC.cpp \
  	VMMAll/IOMAll.cpp \
  	VMMAll/IOMAllMMIO.cpp \
@@ -613,5 +617,5 @@
   VMMR0_SOURCES += \
  	VMMR0/VMMR0TripleFaultHack.cpp \
-	VMMR0/VMMR0TripleFaultHackA.asm
+ 	VMMR0/VMMR0TripleFaultHackA.asm
  endif
  ifdef VBOX_WITH_NETSHAPER
@@ -661,10 +665,10 @@
  VMMLibDTrace_INST    = $(VBOX_INST_DTRACE_LIB)$(KBUILD_TARGET_ARCH)/
  VMMLibDTrace_SOURCES = \
-	dtrace/lib/vbox-types.d \
-	dtrace/lib/$(KBUILD_TARGET_ARCH)/vbox-arch-types.d \
-	$(VMMLibDTrace_0_OUTDIR)/vm.d \
-	$(VMMLibDTrace_0_OUTDIR)/cpumctx.d \
-	$(VMMLibDTrace_0_OUTDIR)/CPUMInternal.d \
-	$(VMMLibDTrace_0_OUTDIR)/x86.d \
+ 	dtrace/lib/vbox-types.d \
+ 	dtrace/lib/$(KBUILD_TARGET_ARCH)/vbox-arch-types.d \
+ 	$(VMMLibDTrace_0_OUTDIR)/vm.d \
+ 	$(VMMLibDTrace_0_OUTDIR)/cpumctx.d \
+ 	$(VMMLibDTrace_0_OUTDIR)/CPUMInternal.d \
+ 	$(VMMLibDTrace_0_OUTDIR)/x86.d \
 
 
Index: /trunk/src/VBox/VMM/VMMAll/GIMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/GIMAll.cpp	(revision 54818)
+++ /trunk/src/VBox/VMM/VMMAll/GIMAll.cpp	(revision 54819)
@@ -154,4 +154,7 @@
             return gimHvReadMsr(pVCpu, idMsr, pRange, puValue);
 
+        case GIMPROVIDERID_KVM:
+            return gimKvmReadMsr(pVCpu, idMsr, pRange, puValue);
+
         default:
             AssertMsgFailed(("GIMReadMsr: for unknown provider %u idMsr=%#RX32 -> #GP(0)", pVM->gim.s.enmProviderId, idMsr));
@@ -188,4 +191,7 @@
             return gimHvWriteMsr(pVCpu, idMsr, pRange, uRawValue);
 
+        case GIMPROVIDERID_KVM:
+            return gimKvmWriteMsr(pVCpu, idMsr, pRange, uRawValue);
+
         default:
             AssertMsgFailed(("GIMWriteMsr: for unknown provider %u idMsr=%#RX32 -> #GP(0)", pVM->gim.s.enmProviderId, idMsr));
Index: /trunk/src/VBox/VMM/VMMAll/GIMAllHv.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/GIMAllHv.cpp	(revision 54818)
+++ /trunk/src/VBox/VMM/VMMAll/GIMAllHv.cpp	(revision 54819)
@@ -154,4 +154,5 @@
 
         default:
+        {
 #ifdef IN_RING3
             static uint32_t s_cTimes = 0;
@@ -161,4 +162,5 @@
             LogFunc(("Unknown/invalid RdMsr (%#RX32) -> #GP(0)\n", idMsr));
             break;
+        }
     }
 
@@ -314,12 +316,14 @@
 
         default:
+        {
 #ifdef IN_RING3
             static uint32_t s_cTimes = 0;
             if (s_cTimes++ < 20)
-                LogRel(("GIM: HyperV: Unknown/invalid WrMsr (%#x,%#x`%08x) -> #GP(0)\n", idMsr, uRawValue & UINT64_C(0xffffffff00000000),
-                        uRawValue & UINT64_C(0xffffffff)));
+                LogRel(("GIM: HyperV: Unknown/invalid WrMsr (%#x,%#x`%08x) -> #GP(0)\n", idMsr,
+                        uRawValue & UINT64_C(0xffffffff00000000), uRawValue & UINT64_C(0xffffffff)));
 #endif
             LogFunc(("Unknown/invalid WrMsr (%#RX32,%#RX64) -> #GP(0)\n", idMsr, uRawValue));
             break;
+        }
     }
 
Index: /trunk/src/VBox/VMM/VMMAll/GIMAllKvm.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/GIMAllKvm.cpp	(revision 54819)
+++ /trunk/src/VBox/VMM/VMMAll/GIMAllKvm.cpp	(revision 54819)
@@ -0,0 +1,229 @@
+/* $Id$ */
+/** @file
+ * GIM - Guest Interface Manager, KVM, All Contexts.
+ */
+
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define LOG_GROUP LOG_GROUP_GIM
+#include "GIMKvmInternal.h"
+#include "GIMInternal.h"
+
+#include <VBox/err.h>
+#include <VBox/vmm/hm.h>
+#include <VBox/vmm/tm.h>
+#include <VBox/vmm/vm.h>
+#include <VBox/vmm/pgm.h>
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/vmm/pdmapi.h>
+
+#include <iprt/asm-amd64-x86.h>
+
+
+/**
+ * Handles the KVM hypercall.
+ *
+ * @returns VBox status code.
+ * @param   pVCpu           Pointer to the VMCPU.
+ * @param   pCtx            Pointer to the guest-CPU context.
+ */
+VMM_INT_DECL(int) gimKvmHypercall(PVMCPU pVCpu, PCPUMCTX pCtx)
+{
+    PVM pVM = pVCpu->CTX_SUFF(pVM);
+    /** @todo Handle hypercalls. Fail for now */
+    return VERR_GIM_IPE_3;
+}
+
+
+/**
+ * Returns whether the guest has configured and enabled the use of KVM's
+ * hypercall interface.
+ *
+ * @returns true if hypercalls are enabled, false otherwise.
+ * @param   pVCpu       Pointer to the VMCPU.
+ */
+VMM_INT_DECL(bool) gimKvmAreHypercallsEnabled(PVMCPU pVCpu)
+{
+    /* KVM paravirt interface doesn't have hypercall control bits like Hyper-V does
+       that guests can control. It's always enabled. */
+    return true;
+}
+
+
+/**
+ * Returns whether the guest has configured and enabled the use of KVM's
+ * paravirtualized TSC.
+ *
+ * @returns true if paravirt. TSC is enabled, false otherwise.
+ * @param   pVM     Pointer to the VM.
+ */
+VMM_INT_DECL(bool) gimKvmIsParavirtTscEnabled(PVM pVM)
+{
+    return false;   /** @todo implement this! */
+}
+
+
+/**
+ * MSR read handler for KVM.
+ *
+ * @returns Strict VBox status code like CPUMQueryGuestMsr().
+ * @retval  VINF_CPUM_R3_MSR_READ
+ * @retval  VERR_CPUM_RAISE_GP_0
+ *
+ * @param   pVCpu       Pointer to the VMCPU.
+ * @param   idMsr       The MSR being read.
+ * @param   pRange      The range this MSR belongs to.
+ * @param   puValue     Where to store the MSR value read.
+ */
+VMM_INT_DECL(VBOXSTRICTRC) gimKvmReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
+{
+    NOREF(pRange);
+    PVM     pVM        = pVCpu->CTX_SUFF(pVM);
+    PGIMKVM pKvm       = &pVM->gim.s.u.Kvm;
+    PGIMKVMCPU pKvmCpu = &pVCpu->gim.s.u.KvmCpu;
+
+    switch (idMsr)
+    {
+        case MSR_GIM_KVM_SYSTEM_TIME:
+        case MSR_GIM_KVM_SYSTEM_TIME_OLD:
+            *puValue = pKvmCpu->u64SystemTimeMsr;
+            return VINF_SUCCESS;
+
+        case MSR_GIM_KVM_WALL_CLOCK:
+        case MSR_GIM_KVM_WALL_CLOCK_OLD:
+            *puValue = pKvm->u64WallClockMsr;
+            return VINF_SUCCESS;
+
+        default:
+        {
+#ifdef IN_RING3
+            static uint32_t s_cTimes = 0;
+            if (s_cTimes++ < 20)
+                LogRel(("GIM: KVM: Unknown/invalid RdMsr (%#x) -> #GP(0)\n", idMsr));
+#endif
+            LogFunc(("Unknown/invalid RdMsr (%#RX32) -> #GP(0)\n", idMsr));
+            break;
+        }
+    }
+
+    return VERR_CPUM_RAISE_GP_0;
+}
+
+
+/**
+ * MSR write handler for KVM.
+ *
+ * @returns Strict VBox status code like CPUMSetGuestMsr().
+ * @retval  VINF_CPUM_R3_MSR_WRITE
+ * @retval  VERR_CPUM_RAISE_GP_0
+ *
+ * @param   pVCpu       Pointer to the VMCPU.
+ * @param   idMsr       The MSR being written.
+ * @param   pRange      The range this MSR belongs to.
+ * @param   uRawValue   The raw value with the ignored bits not masked.
+ */
+VMM_INT_DECL(VBOXSTRICTRC) gimKvmWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uRawValue)
+{
+    NOREF(pRange);
+    PVM     pVM  = pVCpu->CTX_SUFF(pVM);
+    PGIMKVM pKvm = &pVM->gim.s.u.Kvm;
+    PGIMKVMCPU pKvmCpu = &pVCpu->gim.s.u.KvmCpu;
+
+    switch (idMsr)
+    {
+        case MSR_GIM_KVM_SYSTEM_TIME:
+        case MSR_GIM_KVM_SYSTEM_TIME_OLD:
+        {
+#ifndef IN_RING3
+            return VINF_CPUM_R3_MSR_WRITE;
+#else
+            /* Is the guest disabling the system-time struct.? */
+            bool fEnable = RT_BOOL(uRawValue & MSR_GIM_KVM_SYSTEM_TIME_ENABLE_BIT);
+            if (!fEnable)
+            {
+                gimR3KvmDisableSystemTime(pVM);
+                pKvmCpu->u64SystemTimeMsr = uRawValue;
+                return VINF_SUCCESS;
+            }
+
+            /* Is the system-time struct. already enabled? If so, get flags that need preserving. */
+            uint8_t fFlags = 0;
+            GIMKVMSYSTEMTIME SystemTime;
+            RT_ZERO(SystemTime);
+            if (MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(pKvmCpu->u64SystemTimeMsr))
+            {
+                int rc2 = PGMPhysSimpleReadGCPhys(pVM, &SystemTime, pKvmCpu->GCPhysSystemTime, sizeof(GIMKVMSYSTEMTIME));
+                if (RT_SUCCESS(rc2))
+                    fFlags = (SystemTime.fFlags & GIM_KVM_SYSTEM_TIME_FLAGS_GUEST_PAUSED);
+            }
+
+            /* Enable/re-enable the system-time struct. */
+            RTGCPHYS GCPhysSysTime = MSR_GIM_KVM_SYSTEM_TIME_GUEST_GPA(uRawValue);
+            uint32_t uVersion      = pKvmCpu->u32SystemTimeVersion + 2;
+            int rc = gimR3KvmEnableSystemTime(pVM, pVCpu, GCPhysSysTime, uVersion, fFlags);
+            if (RT_SUCCESS(rc))
+            {
+                pKvmCpu->u64SystemTimeMsr     = uRawValue;
+                pKvmCpu->GCPhysSystemTime     = GCPhysSysTime;
+                pKvmCpu->u32SystemTimeVersion = uVersion;
+                return VINF_SUCCESS;
+            }
+
+            return VERR_CPUM_RAISE_GP_0;
+#endif /* IN_RING3 */
+        }
+
+        case MSR_GIM_KVM_WALL_CLOCK:
+        case MSR_GIM_KVM_WALL_CLOCK_OLD:
+        {
+#ifndef IN_RING3
+
+            return VINF_CPUM_R3_MSR_WRITE;
+#else
+            /* Enable the wall-clock struct. */
+            RTGCPHYS GCPhysWallClock = MSR_GIM_KVM_WALL_CLOCK_GUEST_GPA(uRawValue);
+            if (RT_LIKELY(RT_ALIGN_64(GCPhysWallClock, 4) == GCPhysWallClock))
+            {
+                uint32_t uVersion = pKvm->u32WallClockVersion + 2;
+                int rc = gimR3KvmEnableWallClock(pVM, GCPhysWallClock, uVersion);
+                if (RT_SUCCESS(rc))
+                {
+                    pKvm->u64WallClockMsr     = uRawValue;
+                    pKvm->GCPhysWallClock     = GCPhysWallClock;
+                    pKvm->u32WallClockVersion = uVersion;
+                    return VINF_SUCCESS;
+                }
+            }
+            return VERR_CPUM_RAISE_GP_0;
+#endif /* IN_RING3 */
+        }
+
+        default:
+        {
+#ifdef IN_RING3
+            static uint32_t s_cTimes = 0;
+            if (s_cTimes++ < 20)
+                LogRel(("GIM: KVM: Unknown/invalid WrMsr (%#x,%#x`%08x) -> #GP(0)\n", idMsr,
+                        uRawValue & UINT64_C(0xffffffff00000000), uRawValue & UINT64_C(0xffffffff)));
+#endif
+            LogFunc(("Unknown/invalid WrMsr (%#RX32,%#RX64) -> #GP(0)\n", idMsr, uRawValue));
+            break;
+        }
+    }
+
+    return VERR_CPUM_RAISE_GP_0;
+}
+
Index: /trunk/src/VBox/VMM/VMMR0/GIMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/GIMR0.cpp	(revision 54818)
+++ /trunk/src/VBox/VMM/VMMR0/GIMR0.cpp	(revision 54819)
@@ -96,4 +96,7 @@
             return gimR0HvUpdateParavirtTsc(pVM, u64Offset);
 
+        case GIMPROVIDERID_KVM:
+            return VINF_SUCCESS;
+
         case GIMPROVIDERID_NONE:
             return VERR_GIM_NOT_ENABLED;
Index: /trunk/src/VBox/VMM/VMMR3/GIM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/GIM.cpp	(revision 54818)
+++ /trunk/src/VBox/VMM/VMMR3/GIM.cpp	(revision 54819)
@@ -30,15 +30,15 @@
  * ease the guest in running under a recognized, virtualized environment.
  *
- * If the GIM provider configured for the VM needs to be recognized by the guest
- * OS inorder to make use of features supported by the interface. Since it
- * requires co-operation from the guest OS, a GIM provider is also referred to
+ * The GIM provider configured for the VM needs to be recognized by the guest OS
+ * in order to make use of features supported by the interface. Since it
+ * requires co-operation from the guest OS, a GIM provider may also referred to
  * as a paravirtualization interface.
  *
- * One of the ideas behind this, is primarily for making guests more accurate
- * and efficient when operating in a virtualized environment. For instance, a
- * guest OS which interfaces to VirtualBox through a GIM provider may rely on
- * the provider (and VirtualBox ultimately) for providing the correct TSC
- * frequency of the host processor and may therefore not have to caliberate the
- * TSC itself, resulting in higher accuracy and saving several CPU cycles.
+ * One of the goals of having a paravirtualized interface is for enabling guests
+ * to be more accurate and efficient when operating in a virtualized
+ * environment. For instance, a guest OS which interfaces to VirtualBox through
+ * a GIM provider may rely on the provider for supplying the correct TSC
+ * frequency of the host processor. The guest can then avoid caliberating the
+ * TSC itself, resulting in higher accuracy and better performance.
  *
  * At most, only one GIM provider can be active for a running VM and cannot be
@@ -63,4 +63,5 @@
 #include "GIMMinimalInternal.h"
 #include "GIMHvInternal.h"
+#include "GIMKvmInternal.h"
 
 /*******************************************************************************
@@ -68,5 +69,5 @@
 *******************************************************************************/
 static DECLCALLBACK(int) gimR3Save(PVM pVM, PSSMHANDLE pSSM);
-static DECLCALLBACK(int) gimR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
+static DECLCALLBACK(int) gimR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion, uint32_t uPass);
 
 
@@ -136,4 +137,9 @@
             rc = gimR3HvInit(pVM);
         }
+        else if (!RTStrCmp(szProvider, "KVM"))
+        {
+            pVM->gim.s.enmProviderId = GIMPROVIDERID_KVM;
+            rc = gimR3KvmInit(pVM);
+        }
         /** @todo KVM and others. */
         else
@@ -164,7 +170,14 @@
             return gimR3HvInitCompleted(pVM);
 
+        case GIMPROVIDERID_KVM:
+            return gimR3KvmInitCompleted(pVM);
+
         default:
             break;
     }
+
+    if (!TMR3CpuTickIsFixedRateMonotonic(pVM, true /* fWithParavirtEnabled */))
+        LogRel(("GIM: Warning!!! Host TSC is unstable. The guest may behave unpredictably with a paravirtualized clock.\n"));
+
     return VINF_SUCCESS;
 }
@@ -186,7 +199,5 @@
     if (   pVM->gim.s.enmProviderId == GIMPROVIDERID_NONE
         || HMIsEnabled(pVM))
-    {
         return;
-    }
 
     switch (pVM->gim.s.enmProviderId)
@@ -204,5 +215,10 @@
         }
 
-        case GIMPROVIDERID_KVM:            /** @todo KVM. */
+        case GIMPROVIDERID_KVM:
+        {
+            gimR3KvmRelocate(pVM, offDelta);
+            break;
+        }
+
         default:
         {
@@ -252,4 +268,9 @@
             break;
 
+        case GIMPROVIDERID_KVM:
+            rc = gimR3KvmSave(pVM, pSSM);
+            AssertRCReturn(rc, rc);
+            break;
+
         default:
             break;
@@ -269,9 +290,9 @@
  * @param   uPass           The data pass.
  */
-DECLCALLBACK(int) gimR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+DECLCALLBACK(int) gimR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion, uint32_t uPass)
 {
     if (uPass != SSM_PASS_FINAL)
         return VINF_SUCCESS;
-    if (uVersion != GIM_SAVED_STATE_VERSION)
+    if (uSSMVersion != GIM_SAVED_STATE_VERSION)
         return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
 
@@ -311,5 +332,10 @@
     {
         case GIMPROVIDERID_HYPERV:
-            rc = gimR3HvLoad(pVM, pSSM, uVersion);
+            rc = gimR3HvLoad(pVM, pSSM, uSSMVersion);
+            AssertRCReturn(rc, rc);
+            break;
+
+        case GIMPROVIDERID_KVM:
+            rc = gimR3KvmLoad(pVM, pSSM, uSSMVersion);
             AssertRCReturn(rc, rc);
             break;
@@ -339,4 +365,7 @@
             return gimR3HvTerm(pVM);
 
+        case GIMPROVIDERID_KVM:
+            return gimR3KvmTerm(pVM);
+
         default:
             break;
@@ -361,4 +390,7 @@
         case GIMPROVIDERID_HYPERV:
             return gimR3HvReset(pVM);
+
+        case GIMPROVIDERID_KVM:
+            return gimR3KvmReset(pVM);
 
         default:
@@ -403,5 +435,4 @@
             return gimR3HvGetMmio2Regions(pVM, pcRegions);
 
-        case GIMPROVIDERID_KVM:            /** @todo KVM. */
         default:
             break;
Index: /trunk/src/VBox/VMM/VMMR3/GIMHv.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/GIMHv.cpp	(revision 54818)
+++ /trunk/src/VBox/VMM/VMMR3/GIMHv.cpp	(revision 54819)
@@ -380,6 +380,4 @@
     SSMR3PutU32(pSSM, GIM_HV_SAVED_STATE_VERSION);
 
-    /** @todo Save per-VCPU data. */
-
     /*
      * Save per-VM MSRs.
@@ -451,8 +449,6 @@
     if (uHvSavedStatVersion != GIM_HV_SAVED_STATE_VERSION)
         return SSMR3SetLoadError(pSSM, VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION, RT_SRC_POS,
-                                 N_("Unsupported Hyper-V saved state version %u (expected %u)."),
-                                 uHvSavedStatVersion, GIM_HV_SAVED_STATE_VERSION);
-
-    /** @todo Load per-VCPU data. */
+                                 N_("Unsupported Hyper-V saved-state version %u (expected %u)."), uHvSavedStatVersion,
+                                 GIM_HV_SAVED_STATE_VERSION);
 
     /*
Index: /trunk/src/VBox/VMM/VMMR3/GIMKvm.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/GIMKvm.cpp	(revision 54819)
+++ /trunk/src/VBox/VMM/VMMR3/GIMKvm.cpp	(revision 54819)
@@ -0,0 +1,464 @@
+/* $Id$ */
+/** @file
+ * GIM - Guest Interface Manager, KVM implementation.
+ */
+
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define LOG_GROUP LOG_GROUP_GIM
+#include "GIMInternal.h"
+
+#include <iprt/asm-math.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/string.h>
+#include <iprt/mem.h>
+#include <iprt/spinlock.h>
+
+#include <VBox/vmm/cpum.h>
+#include <VBox/vmm/ssm.h>
+#include <VBox/vmm/vm.h>
+#include <VBox/vmm/hm.h>
+#include <VBox/vmm/pdmapi.h>
+#include <VBox/version.h>
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+
+/**
+ * GIM KVM saved-state version.
+ */
+#define GIM_KVM_SAVED_STATE_VERSION         UINT32_C(1)
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+#ifdef VBOX_WITH_STATISTICS
+# define GIMKVM_MSRRANGE(a_uFirst, a_uLast, a_szName) \
+    { (a_uFirst), (a_uLast), kCpumMsrRdFn_Gim, kCpumMsrWrFn_Gim, 0, 0, 0, 0, 0, a_szName, { 0 }, { 0 }, { 0 }, { 0 } }
+#else
+# define GIMKVM_MSRRANGE(a_uFirst, a_uLast, a_szName) \
+    { (a_uFirst), (a_uLast), kCpumMsrRdFn_Gim, kCpumMsrWrFn_Gim, 0, 0, 0, 0, 0, a_szName }
+#endif
+
+/**
+ * Array of MSR ranges supported by KVM.
+ */
+static CPUMMSRRANGE const g_aMsrRanges_Kvm[] =
+{
+    GIMKVM_MSRRANGE(MSR_GIM_KVM_RANGE0_START, MSR_GIM_KVM_RANGE0_END, "KVM range 0"),
+    GIMKVM_MSRRANGE(MSR_GIM_KVM_RANGE1_START, MSR_GIM_KVM_RANGE1_END, "KVM range 1")
+};
+#undef GIMKVM_MSRRANGE
+
+
+/**
+ * Initializes the KVM 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) gimR3KvmInit(PVM pVM)
+{
+    AssertReturn(pVM, VERR_INVALID_PARAMETER);
+    AssertReturn(pVM->gim.s.enmProviderId == GIMPROVIDERID_KVM, VERR_INTERNAL_ERROR_5);
+
+    int rc;
+    PGIMKVM pKvm = &pVM->gim.s.u.Kvm;
+
+    /*
+     * Determine interface capabilities based on the version.
+     */
+    if (!pVM->gim.s.u32Version)
+    {
+        /* Basic features. */
+        pKvm->uBaseFeat = 0
+                        | GIM_KVM_BASE_FEAT_CLOCK_OLD
+                        //| GIM_KVM_BASE_FEAT_NOP_IO_DELAY
+                        //|  GIM_KVM_BASE_FEAT_MMU_OP
+                        | GIM_KVM_BASE_FEAT_CLOCK
+                        //| GIM_KVM_BASE_FEAT_ASYNC_PF
+                        //| GIM_KVM_BASE_FEAT_STEAL_TIME
+                        //| GIM_KVM_BASE_FEAT_PV_EOI
+                        //| GIM_KVM_BASE_FEAT_UNHALT
+                        ;
+        /* Rest of the features are determined in gimR3KvmInitCompleted(). */
+    }
+
+    /*
+     * Expose HVP (Hypervisor Present) bit to the guest.
+     */
+    CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_HVP);
+
+    /*
+     * Modify the standard hypervisor leaves for KVM.
+     */
+    CPUMCPUIDLEAF HyperLeaf;
+    RT_ZERO(HyperLeaf);
+    HyperLeaf.uLeaf        = UINT32_C(0x40000000);
+    HyperLeaf.uEax         = UINT32_C(0x40000001); /* Minimum value for KVM is 0x40000001. */
+    HyperLeaf.uEbx         = 0x4B4D564B;           /* 'KVMK' */
+    HyperLeaf.uEcx         = 0x564B4D56;           /* 'VMKV' */
+    HyperLeaf.uEdx         = 0x0000004D;           /* 'M000' */
+    rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf);
+    AssertLogRelRCReturn(rc, rc);
+
+    /*
+     * Add KVM specific leaves.
+     */
+    HyperLeaf.uLeaf        = UINT32_C(0x40000001);
+    HyperLeaf.uEax         = pKvm->uBaseFeat;
+    HyperLeaf.uEbx         = 0;                    /* Reserved */
+    HyperLeaf.uEcx         = 0;                    /* Reserved */
+    HyperLeaf.uEdx         = 0;                    /* Reserved */
+    rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf);
+    AssertLogRelRCReturn(rc, rc);
+
+    /*
+     * Insert all MSR ranges of KVM.
+     */
+    for (unsigned i = 0; i < RT_ELEMENTS(g_aMsrRanges_Kvm); i++)
+    {
+        rc = CPUMR3MsrRangesInsert(pVM, &g_aMsrRanges_Kvm[i]);
+        AssertLogRelRCReturn(rc, rc);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Initializes remaining bits of the KVM provider.
+ *
+ * This is called after initializing HM and almost all other VMM components.
+ *
+ * @returns VBox status code.
+ * @param   pVM     Pointer to the VM.
+ */
+VMMR3_INT_DECL(int) gimR3KvmInitCompleted(PVM pVM)
+{
+    if (TMR3CpuTickIsFixedRateMonotonic(pVM, true /* fWithParavirtEnabled */))
+    {
+        PGIMKVM pKvm = &pVM->gim.s.u.Kvm;
+        pKvm->uBaseFeat |= GIM_KVM_BASE_FEAT_TSC_STABLE;
+
+        CPUMCPUIDLEAF HyperLeaf;
+        RT_ZERO(HyperLeaf);
+        HyperLeaf.uLeaf        = UINT32_C(0x40000001);
+        HyperLeaf.uEax         = pKvm->uBaseFeat;
+        HyperLeaf.uEbx         = 0;
+        HyperLeaf.uEcx         = 0;
+        HyperLeaf.uEdx         = 0;
+        int rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf);
+        AssertLogRelRCReturn(rc, rc);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Terminates the KVM GIM provider.
+ *
+ * @returns VBox status code.
+ * @param   pVM         Pointer to the VM.
+ */
+VMMR3_INT_DECL(int) gimR3KvmTerm(PVM pVM)
+{
+    gimR3KvmReset(pVM);
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Applies relocations to data and code managed by this component.
+ *
+ * This function will be called at init and whenever the VMM need to relocate
+ * itself inside the GC.
+ *
+ * @param   pVM         Pointer to the VM.
+ * @param   offDelta    Relocation delta relative to old location.
+ */
+VMMR3_INT_DECL(void) gimR3KvmRelocate(PVM pVM, RTGCINTPTR offDelta)
+{
+    NOREF(pVM); NOREF(offDelta);
+}
+
+
+/**
+ * This resets KVM provider MSRs and unmaps whatever KVM regions that
+ * the guest may have mapped.
+ *
+ * This is called when the VM is being reset.
+ *
+ * @param   pVM     Pointer to the VM.
+ * @thread EMT(0).
+ */
+VMMR3_INT_DECL(void) gimR3KvmReset(PVM pVM)
+{
+    VM_ASSERT_EMT0(pVM);
+
+    /*
+     * Reset MSRs.
+     */
+    PGIMKVM pKvm = &pVM->gim.s.u.Kvm;
+    pKvm->u64WallClockMsr = 0;
+    for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++)
+    {
+        PGIMKVMCPU pKvmCpu = &pVM->aCpus[iCpu].gim.s.u.KvmCpu;
+        pKvmCpu->u64SystemTimeMsr = 0;
+    }
+}
+
+
+/**
+ * KVM state-save operation.
+ *
+ * @returns VBox status code.
+ * @param   pVM     Pointer to the VM.
+ * @param   pSSM    Pointer to the SSM handle.
+ */
+VMMR3_INT_DECL(int) gimR3KvmSave(PVM pVM, PSSMHANDLE pSSM)
+{
+    PCGIMKVM pcKvm = &pVM->gim.s.u.Kvm;
+
+    /*
+     * Save the KVM SSM version.
+     */
+    SSMR3PutU32(pSSM, GIM_KVM_SAVED_STATE_VERSION);
+
+    /*
+     * Save per-VCPU data.
+     */
+    for (uint32_t i = 0; i < pVM->cCpus; i++)
+    {
+        PCGIMKVMCPU pcKvmCpu = &pVM->aCpus[i].gim.s.u.KvmCpu;
+
+        /* Guest may alter flags (namely GIM_KVM_SYSTEM_TIME_FLAGS_GUEST_PAUSED bit). So re-read them from guest-memory. */
+        GIMKVMSYSTEMTIME SystemTime;
+        RT_ZERO(SystemTime);
+        if (MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(pcKvmCpu->u64SystemTimeMsr))
+        {
+            int rc = PGMPhysSimpleReadGCPhys(pVM, &SystemTime, pcKvmCpu->GCPhysSystemTime, sizeof(GIMKVMSYSTEMTIME));
+            AssertRCReturn(rc, rc);
+        }
+
+        SSMR3PutU64(pSSM, pcKvmCpu->u64SystemTimeMsr);
+        SSMR3PutGCPhys(pSSM, pcKvmCpu->GCPhysSystemTime);
+        SSMR3PutU32(pSSM, pcKvmCpu->u32SystemTimeVersion);
+        SSMR3PutU8(pSSM, SystemTime.fFlags);
+    }
+
+    /*
+     * Save per-VM data.
+     */
+    SSMR3PutU64(pSSM, pcKvm->u64WallClockMsr);
+    SSMR3PutGCPhys(pSSM, pcKvm->GCPhysWallClock);
+    SSMR3PutU32(pSSM, pcKvm->u32WallClockVersion);
+    return SSMR3PutU32(pSSM, pcKvm->uBaseFeat);
+}
+
+
+/**
+ * KVM state-load operation, final pass.
+ *
+ * @returns VBox status code.
+ * @param   pVM             Pointer to the VM.
+ * @param   pSSM            Pointer to the SSM handle.
+ * @param   uSSMVersion     The GIM saved-state version.
+ */
+VMMR3_INT_DECL(int) gimR3KvmLoad(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion)
+{
+    /*
+     * Load the KVM SSM version first.
+     */
+    uint32_t uKvmSavedStatVersion;
+    int rc = SSMR3GetU32(pSSM, &uKvmSavedStatVersion);
+    AssertRCReturn(rc, rc);
+    if (uKvmSavedStatVersion != GIM_KVM_SAVED_STATE_VERSION)
+        return SSMR3SetLoadError(pSSM, VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION, RT_SRC_POS,
+                                 N_("Unsupported KVM saved-state version %u (expected %u)."), uKvmSavedStatVersion,
+                                 GIM_KVM_SAVED_STATE_VERSION);
+
+    /*
+     * Load per-VCPU data.
+     */
+    for (uint32_t i = 0; i < pVM->cCpus; i++)
+    {
+        PVMCPU     pVCpu   = &pVM->aCpus[i];
+        PGIMKVMCPU pKvmCpu = &pVCpu->gim.s.u.KvmCpu;
+
+        uint8_t fSystemTimeFlags = 0;
+        SSMR3GetU64(pSSM, &pKvmCpu->u64SystemTimeMsr);
+        SSMR3GetGCPhys(pSSM, &pKvmCpu->GCPhysSystemTime);
+        SSMR3GetU32(pSSM, &pKvmCpu->u32SystemTimeVersion);
+        SSMR3GetU8(pSSM, &fSystemTimeFlags);
+
+        /* Enable the system-time struct. if necessary. */
+        if (MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(pKvmCpu->u64SystemTimeMsr))
+        {
+            rc = gimR3KvmEnableSystemTime(pVM, pVCpu, pKvmCpu->GCPhysSystemTime, pKvmCpu->u32SystemTimeVersion, fSystemTimeFlags);
+            AssertRCReturn(rc, rc);
+        }
+    }
+
+    /*
+     * Load per-VM data.
+     */
+    PGIMKVM pKvm = &pVM->gim.s.u.Kvm;
+    SSMR3GetU64(pSSM, &pKvm->u64WallClockMsr);
+    SSMR3GetGCPhys(pSSM, &pKvm->GCPhysWallClock);
+    SSMR3GetU32(pSSM, &pKvm->u32WallClockVersion);
+
+    /** @todo This is wrong, we only need to update it when the guest writes the
+     *        MSR. Remove this and the members in the data structure as
+     *        well. */
+    /* Enable the wall-clock struct. if necessary. */
+    if (MSR_GIM_KVM_WALL_CLOCK_GUEST_GPA(pKvm->u64WallClockMsr))
+    {
+        rc = gimR3KvmEnableWallClock(pVM, pKvm->GCPhysWallClock, pKvm->u32WallClockVersion);
+        AssertRCReturn(rc, rc);
+    }
+
+    rc = SSMR3GetU32(pSSM, &pKvm->uBaseFeat);
+    AssertRCReturn(rc, rc);
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Enables the KVM VCPU system-time structure.
+ *
+ * @returns VBox status code.
+ * @param   pVM                Pointer to the VM.
+ * @param   pVCpu              Pointer to the VMCPU.
+ * @param   GCPhysSystemTime   Guest-physical address of where the VCPU
+ *                             system-time struct. is to be placed.
+ * @param   uVersion           The version value to use.
+ * @param   fFlags             The system-time struct. flags.
+ *
+ * @remarks Don't do any release assertions here, these can be triggered by
+ *          guest R0 code.
+ */
+VMMR3_INT_DECL(int) gimR3KvmEnableSystemTime(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhysSystemTime, uint32_t uVersion, uint8_t fFlags)
+{
+    GIMKVMSYSTEMTIME SystemTime;
+    RT_ZERO(SystemTime);
+    SystemTime.u32Version  = uVersion;
+    SystemTime.u64NanoTS   = TMVirtualGetNoCheck(pVM);  /** @todo better if this is atomic with TMCpuTickGetNoCheck() */
+    SystemTime.u64Tsc      = TMCpuTickGetNoCheck(pVCpu);
+    SystemTime.fFlags      = fFlags | GIM_KVM_SYSTEM_TIME_FLAGS_TSC_STABLE;
+
+    /*
+     * How the guest calculates the system time (nanoseconds):
+     *
+     * tsc = rdtsc - SysTime.u64Tsc
+     * if (SysTime.i8TscShift >= 0)
+     *     tsc <<= i8TscShift;
+     * else
+     *     tsc >>= -i8TscShift;
+     * time = ((tsc * SysTime.u32TscScale) >> 32) + SysTime.u64NanoTS
+     */
+    uint64_t u64TscFreq = TMCpuTicksPerSecond(pVM);
+    SystemTime.i8TscShift  = 0;
+    while (u64TscFreq > 2 * RT_NS_1SEC_64)
+    {
+        u64TscFreq >>= 1;
+        SystemTime.i8TscShift--;
+    }
+    uint32_t uTscFreqLo = (uint32_t)u64TscFreq;
+    while (uTscFreqLo <= RT_NS_1SEC)
+    {
+        uTscFreqLo <<= 1;
+        SystemTime.i8TscShift++;
+    }
+    SystemTime.u32TscScale = ASMDivU64ByU32RetU32(RT_NS_1SEC_64 << 32, uTscFreqLo);
+
+    Assert(!(SystemTime.u32Version & UINT32_C(1)));
+    Assert(PGMPhysIsGCPhysNormal(pVM, GCPhysSystemTime));
+    int rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysSystemTime, &SystemTime, sizeof(GIMKVMSYSTEMTIME));
+    if (RT_SUCCESS(rc))
+    {
+        LogRel(("GIM: KVM: VCPU%3d: Enabled system-time struct. at %#RGp - u32TscScale=%#RX32 i8TscShift=%d uVersion=%#RU32 "
+                "fFlags=%#x\n", pVCpu->idCpu, GCPhysSystemTime, SystemTime.u32TscScale, SystemTime.i8TscShift,
+                SystemTime.u32Version, SystemTime.fFlags));
+        TMR3CpuTickParavirtEnable(pVM);
+    }
+    else
+        LogRel(("GIM: KVM: VCPU%3d: Failed to write system-time struct. at %#RGp. rc=%Rrc\n", GCPhysSystemTime, rc));
+
+    return rc;
+}
+
+
+/**
+ * Disables the KVM system-time struct.
+ *
+ * @returns VBox status code.
+ * @param   pVM     Pointer to the VM.
+ */
+VMMR3_INT_DECL(int) gimR3KvmDisableSystemTime(PVM pVM)
+{
+    TMR3CpuTickParavirtDisable(pVM);
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Enables the KVM wall-clock structure.
+ *
+ * @returns VBox status code.
+ * @param   pVM                Pointer to the VM.
+ * @param   GCPhysWallClock    Where the guest wall-clock structure is located.
+ * @param   uVersion           The version (sequence number) value to use.
+ *
+ * @remarks Don't do any release assertions here, these can be triggered by
+ *          guest R0 code.
+ */
+VMMR3_INT_DECL(int) gimR3KvmEnableWallClock(PVM pVM, RTGCPHYS GCPhysWallClock, uint32_t uVersion)
+{
+    RTTIMESPEC TimeSpec;
+    int32_t    iSec;
+    int32_t    iNano;
+
+    TMR3UtcNow(pVM, &TimeSpec);
+    RTTimeSpecGetSecondsAndNano(&TimeSpec, &iSec, &iNano);
+
+    GIMKVMWALLCLOCK WallClock;
+    RT_ZERO(WallClock);
+    WallClock.u32Version = uVersion;
+    WallClock.u32Sec     = iSec;
+    WallClock.u32Nano    = iNano;
+
+    Assert(PGMPhysIsGCPhysNormal(pVM, GCPhysWallClock));
+    Assert(!(WallClock.u32Version & UINT32_C(1)));
+    int rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysWallClock, &WallClock, sizeof(GIMKVMWALLCLOCK));
+    if (RT_SUCCESS(rc))
+    {
+        LogRel(("GIM: KVM: Enabled wall-clock struct. at %#RGp - u32Sec=%u u32Nano=%u uVersion=%#RU32\n", GCPhysWallClock,
+                WallClock.u32Sec, WallClock.u32Nano, WallClock.u32Version));
+    }
+    else
+        LogRel(("GIM: KVM: Failed to write wall-clock struct. at %#RGp. rc=%Rrc\n", GCPhysWallClock, rc));
+
+    return rc;
+}
+
Index: /trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp	(revision 54818)
+++ /trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp	(revision 54819)
@@ -4574,6 +4574,8 @@
 
     /** @todo What about ballooning of large pages??! */
+#if 0
     Assert(   PGM_PAGE_GET_PDE_TYPE(pPage) != PGM_PAGE_PDE_TYPE_PDE
            && PGM_PAGE_GET_PDE_TYPE(pPage) != PGM_PAGE_PDE_TYPE_PDE_DISABLED);
+#endif
 
     if (    PGM_PAGE_IS_ZERO(pPage)
Index: /trunk/src/VBox/VMM/include/GIMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/GIMInternal.h	(revision 54818)
+++ /trunk/src/VBox/VMM/include/GIMInternal.h	(revision 54819)
@@ -21,4 +21,5 @@
 #include <VBox/vmm/gim.h>
 #include "GIMHvInternal.h"
+#include "GIMKvmInternal.h"
 #include "GIMMinimalInternal.h"
 
@@ -73,6 +74,5 @@
     {
         GIMHV Hv;
-
-        /** @todo KVM and others. */
+        GIMKVM Kvm;
     } u;
 } GIM;
@@ -86,4 +86,8 @@
 typedef struct GIMCPU
 {
+    union
+    {
+        GIMKVMCPU KvmCpu;
+    } u;
 } GIMCPU;
 /** Pointer to GIM VMCPU instance data. */
Index: /trunk/src/VBox/VMM/include/GIMKvmInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/GIMKvmInternal.h	(revision 54819)
+++ /trunk/src/VBox/VMM/include/GIMKvmInternal.h	(revision 54819)
@@ -0,0 +1,248 @@
+/* $Id$ */
+/** @file
+ * GIM - KVM, Internal header file.
+ */
+
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ___GIMKvmInternal_h
+#define ___GIMKvmInternal_h
+
+#include <VBox/vmm/gim.h>
+#include <VBox/vmm/cpum.h>
+
+
+/** @name KVM base features.
+ * @{
+ */
+/** Old, deprecated clock source available. */
+#define GIM_KVM_BASE_FEAT_CLOCK_OLD                RT_BIT(0)
+/** No need for artifical delays on IO operations. */
+#define GIM_KVM_BASE_FEAT_NOP_IO_DELAY             RT_BIT(1)
+/** MMU op supported (deprecated, unused). */
+#define GIM_KVM_BASE_FEAT_MMU_OP                   RT_BIT(2)
+/** Clock source available. */
+#define GIM_KVM_BASE_FEAT_CLOCK                    RT_BIT(3)
+/** Asynchronous page faults supported. */
+#define GIM_KVM_BASE_FEAT_ASYNC_PF                 RT_BIT(4)
+/** Steal time (VCPU not executing guest code time in ns) available. */
+#define GIM_KVM_BASE_FEAT_STEAL_TIME               RT_BIT(5)
+/** Paravirtualized EOI (end-of-interrupt) supported. */
+#define GIM_KVM_BASE_FEAT_PV_EOI                   RT_BIT(6)
+/** Paravirtualized spinlock (unhalting VCPU) supported. */
+#define GIM_KVM_BASE_FEAT_PV_UNHALT                RT_BIT(7)
+/** The TSC is stable (fixed rate, monotonic). */
+#define GIM_KVM_BASE_FEAT_TSC_STABLE               RT_BIT(24)
+/** @}  */
+
+
+/** @name KVM MSRs.
+ * @{
+ */
+/** Start of range 0. */
+#define MSR_GIM_KVM_RANGE0_START                   UINT32_C(0x11)
+/** Old, deprecated wall clock. */
+#define MSR_GIM_KVM_WALL_CLOCK_OLD                 UINT32_C(0x11)
+/** Old, deprecated System time. */
+#define MSR_GIM_KVM_SYSTEM_TIME_OLD                UINT32_C(0x12)
+/** End of range 0. */
+#define MSR_GIM_KVM_RANGE0_END                     MSR_GIM_KVM_SYSTEM_TIME_OLD
+
+/** Start of range 1. */
+#define MSR_GIM_KVM_RANGE1_START                   UINT32_C(0x4b564d00)
+/** Wall clock. */
+#define MSR_GIM_KVM_WALL_CLOCK                     UINT32_C(0x4b564d00)
+/** System time. */
+#define MSR_GIM_KVM_SYSTEM_TIME                    UINT32_C(0x4b564d01)
+/** Asynchronous page fault. */
+#define MSR_GIM_KVM_ASYNC_PF                       UINT32_C(0x4b564d02)
+/** Steal time. */
+#define MSR_GIM_KVM_STEAL_TIME                     UINT32_C(0x4b564d03)
+/** Paravirtualized EOI (end-of-interrupt). */
+#define MSR_GIM_KVM_EOI                            UINT32_C(0x4b564d04)
+/** End of range 1. */
+#define MSR_GIM_KVM_RANGE1_END                     MSR_GIM_KVM_EOI
+
+AssertCompile(MSR_GIM_KVM_RANGE0_START <= MSR_GIM_KVM_RANGE0_END);
+AssertCompile(MSR_GIM_KVM_RANGE1_START <= MSR_GIM_KVM_RANGE1_END);
+
+/** KVM page size.  */
+#define GIM_KVM_PAGE_SIZE                          0x1000
+
+/**
+ * MMIO2 region indices.
+ */
+/** The system time page(s) region. */
+#define GIM_KVM_SYSTEM_TIME_PAGE_REGION_IDX        UINT8_C(0)
+/** The steal time page(s) region. */
+#define GIM_KVM_STEAL_TIME_PAGE_REGION_IDX         UINT8_C(1)
+/** The maximum region index (must be <= UINT8_MAX). */
+#define GIM_KVM_REGION_IDX_MAX                     GIM_KVM_STEAL_TIME_PAGE_REGION_IDX
+
+/**
+ * KVM system-time structure (GIM_KVM_SYSTEM_TIME_FLAGS_XXX) flags.
+ * See "Documentation/virtual/kvm/api.txt".
+ */
+/** The TSC is stable (monotonic). */
+#define GIM_KVM_SYSTEM_TIME_FLAGS_TSC_STABLE       RT_BIT(0)
+/** The guest VCPU has been paused by the hypervisor. */
+#define GIM_KVM_SYSTEM_TIME_FLAGS_GUEST_PAUSED     RT_BIT(1)
+/** */
+
+/** @name KVM MSR - System time (MSR_GIM_KVM_SYSTEM_TIME and
+ * MSR_GIM_KVM_SYSTEM_TIME_OLD).
+ * @{
+ */
+/** The system-time enable bit. */
+#define MSR_GIM_KVM_SYSTEM_TIME_ENABLE_BIT        RT_BIT_64(0)
+/** Whether the system-time struct. is enabled or not. */
+#define MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(a)     RT_BOOL((a) & MSR_GIM_KVM_SYSTEM_TIME_ENABLE_BIT)
+/** Guest-physical address of the system-time struct. */
+#define MSR_GIM_KVM_SYSTEM_TIME_GUEST_GPA(a)      ((a) & ~MSR_GIM_KVM_SYSTEM_TIME_ENABLE_BIT)
+/** @} */
+
+/** @name KVM MSR - Wall clock (MSR_GIM_KVM_WALL_CLOCK and
+ * MSR_GIM_KVM_WALL_CLOCK_OLD).
+ * @{
+ */
+/** Guest-physical address of the wall-clock struct. */
+#define MSR_GIM_KVM_WALL_CLOCK_GUEST_GPA(a)      (a)
+/** @} */
+
+
+/**
+ * KVM per-VCPU system-time structure.
+ */
+typedef struct GIMKVMSYSTEMTIME
+{
+    /** Version (sequence number). */
+    uint32_t        u32Version;
+    /** Alignment padding. */
+    uint32_t        u32Padding0;
+    /** TSC time stamp.  */
+    uint64_t        u64Tsc;
+    /** System time in nanoseconds. */
+    uint64_t        u64NanoTS;
+    /** TSC to system time scale factor. */
+    uint32_t        u32TscScale;
+    /** TSC frequency shift.  */
+    int8_t          i8TscShift;
+    /** Clock source (GIM_KVM_SYSTEM_TIME_FLAGS_XXX) flags. */
+    uint8_t         fFlags;
+    /** Alignment padding. */
+    uint8_t         abPadding0[2];
+} GIMKVMSYSTEMTIME;
+/** Pointer to KVM system-time struct. */
+typedef GIMKVMSYSTEMTIME *PGIMKVMSYSTEMTIME;
+/** Pointer to a const KVM system-time struct. */
+typedef GIMKVMSYSTEMTIME const *PCGIMKVMSYSTEMTIME;
+AssertCompileSize(GIMKVMSYSTEMTIME, 32);
+
+
+/**
+ * KVM per-VM wall-clock structure.
+ */
+typedef struct GIMKVMWALLCLOCK
+{
+    /** Version (sequence number). */
+    uint32_t        u32Version;
+    /** Number of seconds since boot. */
+    uint32_t        u32Sec;
+    /** Number of nanoseconds since boot. */
+    uint32_t        u32Nano;
+} GIMKVMWALLCLOCK;
+/** Pointer to KVM wall-clock struct. */
+typedef GIMKVMWALLCLOCK *PGIMKVMWALLCLOCK;
+/** Pointer to a const KVM wall-clock struct. */
+typedef GIMKVMWALLCLOCK const *PCGIMKVMWALLCLOCK;
+AssertCompileSize(GIMKVMWALLCLOCK, 12);
+
+
+/**
+ * GIM KVMV VM instance data.
+ * Changes to this must checked against the padding of the gim union in VM!
+ */
+typedef struct GIMKVM
+{
+    /** @name MSRs & related data. */
+    /** Wall-clock MSR. */
+    uint64_t                    u64WallClockMsr;
+    /** Guest-physical address of the wall-clock struct. */
+    RTGCPHYS                    GCPhysWallClock;
+    /** The version (sequence number) of the wall-clock struct. */
+    uint32_t                    u32WallClockVersion;
+    /** @} */
+
+    /** @name CPUID features. */
+    /** Basic features. */
+    uint32_t                    uBaseFeat;
+    /** @} */
+} GIMKVM;
+/** Pointer to per-VM GIM KVM instance data. */
+typedef GIMKVM *PGIMKVM;
+/** Pointer to const per-VM GIM KVM instance data. */
+typedef GIMKVM const *PCGIMKVM;
+
+/**
+ * GIM KVMV VCPU instance data.
+ * Changes to this must checked against the padding of the gim union in VMCPU!
+ */
+typedef struct GIMKVMCPU
+{
+    /** System-time MSR. */
+    uint64_t                    u64SystemTimeMsr;
+    /** The guest-physical address of the system-time struct. */
+    RTGCPHYS                    GCPhysSystemTime;
+    /** The version (sequence number) of the system-time struct. */
+    uint32_t                    u32SystemTimeVersion;
+} GIMKVMCPU;
+/** Pointer to per-VCPU GIM KVM instance data. */
+typedef GIMKVMCPU *PGIMKVMCPU;
+/** Pointer to const per-VCPU GIM KVM instance data. */
+typedef GIMKVMCPU const *PCGIMKVMCPU;
+
+
+RT_C_DECLS_BEGIN
+
+#ifdef IN_RING0
+#if 0
+VMMR0_INT_DECL(int)             gimR0KvmInitVM(PVM pVM);
+VMMR0_INT_DECL(int)             gimR0KvmTermVM(PVM pVM);
+VMMR0_INT_DECL(int)             gimR0KvmUpdateParavirtTsc(PVM pVM, uint64_t u64Offset);
+#endif
+#endif /* IN_RING0 */
+
+#ifdef IN_RING3
+VMMR3_INT_DECL(int)             gimR3KvmInit(PVM pVM);
+VMMR3_INT_DECL(int)             gimR3KvmInitCompleted(PVM pVM);
+VMMR3_INT_DECL(int)             gimR3KvmTerm(PVM pVM);
+VMMR3_INT_DECL(void)            gimR3KvmRelocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3_INT_DECL(void)            gimR3KvmReset(PVM pVM);
+VMMR3_INT_DECL(int)             gimR3KvmSave(PVM pVM, PSSMHANDLE pSSM);
+VMMR3_INT_DECL(int)             gimR3KvmLoad(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion);
+
+VMMR3_INT_DECL(int)             gimR3KvmDisableSystemTime(PVM pVM);
+VMMR3_INT_DECL(int)             gimR3KvmEnableSystemTime(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhysSysTime, uint32_t uVersion, uint8_t fFlags);
+VMMR3_INT_DECL(int)             gimR3KvmEnableWallClock(PVM pVM, RTGCPHYS GCPhysSysTime, uint32_t uVersion);
+#endif /* IN_RING3 */
+
+VMM_INT_DECL(bool)              gimKvmIsParavirtTscEnabled(PVM pVM);
+VMM_INT_DECL(bool)              gimKvmAreHypercallsEnabled(PVMCPU pVCpu);
+VMM_INT_DECL(int)               gimKvmHypercall(PVMCPU pVCpu, PCPUMCTX pCtx);
+VMM_INT_DECL(VBOXSTRICTRC)      gimKvmReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue);
+VMM_INT_DECL(VBOXSTRICTRC)      gimKvmWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uRawValue);
+
+RT_C_DECLS_END
+
+#endif
+
