0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/* $Id$ */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/** @file
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * GIM - Guest Interface Manager, KVM implementation.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Copyright (C) 2015 Oracle Corporation
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * available from http://www.virtualbox.org. This file is free software;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * you can redistribute it and/or modify it under the terms of the GNU
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * General Public License (GPL) as published by the Free Software
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/*******************************************************************************
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync* Header Files *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync*******************************************************************************/
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#define LOG_GROUP LOG_GROUP_GIM
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include "GIMInternal.h"
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include <iprt/asm-math.h>
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include <iprt/assert.h>
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include <iprt/err.h>
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include <iprt/string.h>
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include <iprt/mem.h>
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include <iprt/spinlock.h>
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include <VBox/vmm/cpum.h>
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync#include <VBox/disopcode.h>
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include <VBox/vmm/ssm.h>
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include <VBox/vmm/vm.h>
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include <VBox/vmm/hm.h>
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include <VBox/vmm/pdmapi.h>
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include <VBox/version.h>
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/*******************************************************************************
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync* Defined Constants And Macros *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync*******************************************************************************/
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/**
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * GIM KVM saved-state version.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#define GIM_KVM_SAVED_STATE_VERSION UINT32_C(1)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/*******************************************************************************
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync* Global Variables *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync*******************************************************************************/
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#ifdef VBOX_WITH_STATISTICS
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync# define GIMKVM_MSRRANGE(a_uFirst, a_uLast, a_szName) \
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync { (a_uFirst), (a_uLast), kCpumMsrRdFn_Gim, kCpumMsrWrFn_Gim, 0, 0, 0, 0, 0, a_szName, { 0 }, { 0 }, { 0 }, { 0 } }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#else
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync# define GIMKVM_MSRRANGE(a_uFirst, a_uLast, a_szName) \
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync { (a_uFirst), (a_uLast), kCpumMsrRdFn_Gim, kCpumMsrWrFn_Gim, 0, 0, 0, 0, 0, a_szName }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#endif
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/**
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Array of MSR ranges supported by KVM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncstatic CPUMMSRRANGE const g_aMsrRanges_Kvm[] =
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync{
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync GIMKVM_MSRRANGE(MSR_GIM_KVM_RANGE0_START, MSR_GIM_KVM_RANGE0_END, "KVM range 0"),
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync GIMKVM_MSRRANGE(MSR_GIM_KVM_RANGE1_START, MSR_GIM_KVM_RANGE1_END, "KVM range 1")
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync};
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#undef GIMKVM_MSRRANGE
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/**
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Initializes the KVM GIM provider.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @returns VBox status code.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pVM Pointer to the VM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param uVersion The interface version this VM should use.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncVMMR3_INT_DECL(int) gimR3KvmInit(PVM pVM)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync{
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync AssertReturn(pVM, VERR_INVALID_PARAMETER);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync AssertReturn(pVM->gim.s.enmProviderId == GIMPROVIDERID_KVM, VERR_INTERNAL_ERROR_5);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync int rc;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync PGIMKVM pKvm = &pVM->gim.s.u.Kvm;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Determine interface capabilities based on the version.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync if (!pVM->gim.s.u32Version)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /* Basic features. */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync pKvm->uBaseFeat = 0
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync | GIM_KVM_BASE_FEAT_CLOCK_OLD
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync //| GIM_KVM_BASE_FEAT_NOP_IO_DELAY
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync //| GIM_KVM_BASE_FEAT_MMU_OP
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync | GIM_KVM_BASE_FEAT_CLOCK
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync //| GIM_KVM_BASE_FEAT_ASYNC_PF
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync //| GIM_KVM_BASE_FEAT_STEAL_TIME
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync //| GIM_KVM_BASE_FEAT_PV_EOI
9c178a84047ec38c02debb747cbdc7de4531d940vboxsync | GIM_KVM_BASE_FEAT_PV_UNHALT
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync ;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /* Rest of the features are determined in gimR3KvmInitCompleted(). */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Expose HVP (Hypervisor Present) bit to the guest.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_HVP);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Modify the standard hypervisor leaves for KVM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync CPUMCPUIDLEAF HyperLeaf;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync RT_ZERO(HyperLeaf);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uLeaf = UINT32_C(0x40000000);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uEax = UINT32_C(0x40000001); /* Minimum value for KVM is 0x40000001. */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uEbx = 0x4B4D564B; /* 'KVMK' */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uEcx = 0x564B4D56; /* 'VMKV' */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uEdx = 0x0000004D; /* 'M000' */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync AssertLogRelRCReturn(rc, rc);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Add KVM specific leaves.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uLeaf = UINT32_C(0x40000001);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uEax = pKvm->uBaseFeat;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uEbx = 0; /* Reserved */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uEcx = 0; /* Reserved */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uEdx = 0; /* Reserved */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync AssertLogRelRCReturn(rc, rc);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Insert all MSR ranges of KVM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync for (unsigned i = 0; i < RT_ELEMENTS(g_aMsrRanges_Kvm); i++)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync rc = CPUMR3MsrRangesInsert(pVM, &g_aMsrRanges_Kvm[i]);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync AssertLogRelRCReturn(rc, rc);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync /*
66d96ba0c4c722996a3a1e6d92403a14a27db1b4vboxsync * Setup hypercall and #UD handling.
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync */
66d96ba0c4c722996a3a1e6d92403a14a27db1b4vboxsync for (VMCPUID i = 0; i < pVM->cCpus; i++)
66d96ba0c4c722996a3a1e6d92403a14a27db1b4vboxsync VMMHypercallsEnable(&pVM->aCpus[i]);
66d96ba0c4c722996a3a1e6d92403a14a27db1b4vboxsync
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync if (ASMIsAmdCpu())
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync {
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync pKvm->fTrapXcptUD = true;
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync pKvm->uOpCodeNative = OP_VMMCALL;
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync }
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync else
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync {
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync Assert(ASMIsIntelCpu() || ASMIsViaCentaurCpu());
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync pKvm->fTrapXcptUD = false;
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync pKvm->uOpCodeNative = OP_VMCALL;
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync }
66d96ba0c4c722996a3a1e6d92403a14a27db1b4vboxsync
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync /* We always need to trap VMCALL/VMMCALL hypercall using #UDs for raw-mode VMs. */
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync if (!HMIsEnabled(pVM))
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync pKvm->fTrapXcptUD = true;
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync return VINF_SUCCESS;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync}
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/**
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Initializes remaining bits of the KVM provider.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * This is called after initializing HM and almost all other VMM components.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @returns VBox status code.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pVM Pointer to the VM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncVMMR3_INT_DECL(int) gimR3KvmInitCompleted(PVM pVM)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync{
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync if (TMR3CpuTickIsFixedRateMonotonic(pVM, true /* fWithParavirtEnabled */))
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync PGIMKVM pKvm = &pVM->gim.s.u.Kvm;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync pKvm->uBaseFeat |= GIM_KVM_BASE_FEAT_TSC_STABLE;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync CPUMCPUIDLEAF HyperLeaf;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync RT_ZERO(HyperLeaf);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uLeaf = UINT32_C(0x40000001);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uEax = pKvm->uBaseFeat;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uEbx = 0;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uEcx = 0;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync HyperLeaf.uEdx = 0;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync int rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync AssertLogRelRCReturn(rc, rc);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync return VINF_SUCCESS;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync}
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/**
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Terminates the KVM GIM provider.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @returns VBox status code.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pVM Pointer to the VM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncVMMR3_INT_DECL(int) gimR3KvmTerm(PVM pVM)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync{
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync gimR3KvmReset(pVM);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync return VINF_SUCCESS;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync}
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/**
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Applies relocations to data and code managed by this component.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * This function will be called at init and whenever the VMM need to relocate
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * itself inside the GC.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pVM Pointer to the VM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param offDelta Relocation delta relative to old location.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncVMMR3_INT_DECL(void) gimR3KvmRelocate(PVM pVM, RTGCINTPTR offDelta)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync{
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync NOREF(pVM); NOREF(offDelta);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync}
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/**
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * This resets KVM provider MSRs and unmaps whatever KVM regions that
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * the guest may have mapped.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * This is called when the VM is being reset.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pVM Pointer to the VM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @thread EMT(0).
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncVMMR3_INT_DECL(void) gimR3KvmReset(PVM pVM)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync{
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync VM_ASSERT_EMT0(pVM);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Reset MSRs.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync PGIMKVM pKvm = &pVM->gim.s.u.Kvm;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync pKvm->u64WallClockMsr = 0;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync PGIMKVMCPU pKvmCpu = &pVM->aCpus[iCpu].gim.s.u.KvmCpu;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync pKvmCpu->u64SystemTimeMsr = 0;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync}
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/**
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * KVM state-save operation.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @returns VBox status code.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pVM Pointer to the VM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pSSM Pointer to the SSM handle.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncVMMR3_INT_DECL(int) gimR3KvmSave(PVM pVM, PSSMHANDLE pSSM)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync{
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync PCGIMKVM pcKvm = &pVM->gim.s.u.Kvm;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Save the KVM SSM version.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SSMR3PutU32(pSSM, GIM_KVM_SAVED_STATE_VERSION);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Save per-VCPU data.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync for (uint32_t i = 0; i < pVM->cCpus; i++)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync PCGIMKVMCPU pcKvmCpu = &pVM->aCpus[i].gim.s.u.KvmCpu;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /* Guest may alter flags (namely GIM_KVM_SYSTEM_TIME_FLAGS_GUEST_PAUSED bit). So re-read them from guest-memory. */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync GIMKVMSYSTEMTIME SystemTime;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync RT_ZERO(SystemTime);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync if (MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(pcKvmCpu->u64SystemTimeMsr))
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync int rc = PGMPhysSimpleReadGCPhys(pVM, &SystemTime, pcKvmCpu->GCPhysSystemTime, sizeof(GIMKVMSYSTEMTIME));
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync AssertRCReturn(rc, rc);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SSMR3PutU64(pSSM, pcKvmCpu->u64SystemTimeMsr);
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync SSMR3PutU64(pSSM, pcKvmCpu->uTsc);
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync SSMR3PutU64(pSSM, pcKvmCpu->uVirtNanoTS);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SSMR3PutGCPhys(pSSM, pcKvmCpu->GCPhysSystemTime);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SSMR3PutU32(pSSM, pcKvmCpu->u32SystemTimeVersion);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SSMR3PutU8(pSSM, SystemTime.fFlags);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Save per-VM data.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SSMR3PutU64(pSSM, pcKvm->u64WallClockMsr);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync return SSMR3PutU32(pSSM, pcKvm->uBaseFeat);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync}
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/**
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * KVM state-load operation, final pass.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @returns VBox status code.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pVM Pointer to the VM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pSSM Pointer to the SSM handle.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param uSSMVersion The GIM saved-state version.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncVMMR3_INT_DECL(int) gimR3KvmLoad(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync{
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Load the KVM SSM version first.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync uint32_t uKvmSavedStatVersion;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync int rc = SSMR3GetU32(pSSM, &uKvmSavedStatVersion);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync AssertRCReturn(rc, rc);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync if (uKvmSavedStatVersion != GIM_KVM_SAVED_STATE_VERSION)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync return SSMR3SetLoadError(pSSM, VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION, RT_SRC_POS,
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync N_("Unsupported KVM saved-state version %u (expected %u)."), uKvmSavedStatVersion,
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync GIM_KVM_SAVED_STATE_VERSION);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Load per-VCPU data.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync for (uint32_t i = 0; i < pVM->cCpus; i++)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync PVMCPU pVCpu = &pVM->aCpus[i];
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync PGIMKVMCPU pKvmCpu = &pVCpu->gim.s.u.KvmCpu;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync uint8_t fSystemTimeFlags = 0;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SSMR3GetU64(pSSM, &pKvmCpu->u64SystemTimeMsr);
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync SSMR3GetU64(pSSM, &pKvmCpu->uTsc);
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync SSMR3GetU64(pSSM, &pKvmCpu->uVirtNanoTS);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SSMR3GetGCPhys(pSSM, &pKvmCpu->GCPhysSystemTime);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SSMR3GetU32(pSSM, &pKvmCpu->u32SystemTimeVersion);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SSMR3GetU8(pSSM, &fSystemTimeFlags);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /* Enable the system-time struct. if necessary. */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync if (MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(pKvmCpu->u64SystemTimeMsr))
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0a33719d5fae07578c41ffd2dd7810bf835387c8vboxsync Assert(!TMVirtualIsTicking(pVM)); /* paranoia. */
0a33719d5fae07578c41ffd2dd7810bf835387c8vboxsync Assert(!TMCpuTickIsTicking(pVCpu));
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync rc = gimR3KvmEnableSystemTime(pVM, pVCpu, pKvmCpu, fSystemTimeFlags);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync AssertRCReturn(rc, rc);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Load per-VM data.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync PGIMKVM pKvm = &pVM->gim.s.u.Kvm;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SSMR3GetU64(pSSM, &pKvm->u64WallClockMsr);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync rc = SSMR3GetU32(pSSM, &pKvm->uBaseFeat);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync AssertRCReturn(rc, rc);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync return VINF_SUCCESS;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync}
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/**
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Enables the KVM VCPU system-time structure.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @returns VBox status code.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pVM Pointer to the VM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pVCpu Pointer to the VMCPU.
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync * @param pKvmCpu Pointer to the GIMKVMCPU with all fields
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync * populated by the caller.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param fFlags The system-time struct. flags.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @remarks Don't do any release assertions here, these can be triggered by
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * guest R0 code.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsyncVMMR3_INT_DECL(int) gimR3KvmEnableSystemTime(PVM pVM, PVMCPU pVCpu, PGIMKVMCPU pKvmCpu, uint8_t fFlags)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync{
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync GIMKVMSYSTEMTIME SystemTime;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync RT_ZERO(SystemTime);
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync SystemTime.u32Version = pKvmCpu->u32SystemTimeVersion;
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync SystemTime.u64NanoTS = pKvmCpu->uVirtNanoTS;
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync SystemTime.u64Tsc = pKvmCpu->uTsc;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SystemTime.fFlags = fFlags | GIM_KVM_SYSTEM_TIME_FLAGS_TSC_STABLE;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync /*
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * How the guest calculates the system time (nanoseconds):
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * tsc = rdtsc - SysTime.u64Tsc
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * if (SysTime.i8TscShift >= 0)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * tsc <<= i8TscShift;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * else
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * tsc >>= -i8TscShift;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * time = ((tsc * SysTime.u32TscScale) >> 32) + SysTime.u64NanoTS
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync uint64_t u64TscFreq = TMCpuTicksPerSecond(pVM);
fa35e2dfd910e18dbb7f136bfe56030e5116d51cvboxsync SystemTime.i8TscShift = 0;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync while (u64TscFreq > 2 * RT_NS_1SEC_64)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync u64TscFreq >>= 1;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SystemTime.i8TscShift--;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync uint32_t uTscFreqLo = (uint32_t)u64TscFreq;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync while (uTscFreqLo <= RT_NS_1SEC)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync uTscFreqLo <<= 1;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SystemTime.i8TscShift++;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync SystemTime.u32TscScale = ASMDivU64ByU32RetU32(RT_NS_1SEC_64 << 32, uTscFreqLo);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync Assert(!(SystemTime.u32Version & UINT32_C(1)));
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync Assert(PGMPhysIsGCPhysNormal(pVM, pKvmCpu->GCPhysSystemTime));
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync int rc = PGMPhysSimpleWriteGCPhys(pVM, pKvmCpu->GCPhysSystemTime, &SystemTime, sizeof(GIMKVMSYSTEMTIME));
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync if (RT_SUCCESS(rc))
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync LogRel(("GIM: KVM: VCPU%3d: Enabled system-time struct. at %#RGp - u32TscScale=%#RX32 i8TscShift=%d uVersion=%#RU32 "
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync "fFlags=%#x uTsc=%#RX64 uVirtNanoTS=%#RX64\n", pVCpu->idCpu, pKvmCpu->GCPhysSystemTime, SystemTime.u32TscScale,
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync SystemTime.i8TscShift, SystemTime.u32Version, SystemTime.fFlags, pKvmCpu->uTsc, pKvmCpu->uVirtNanoTS));
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync TMR3CpuTickParavirtEnable(pVM);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync else
6fd7ca38c2e6dbc9871b33b11cf70ed6bf4e7d03vboxsync LogRel(("GIM: KVM: VCPU%3d: Failed to write system-time struct. at %#RGp. rc=%Rrc\n", pKvmCpu->GCPhysSystemTime, rc));
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync return rc;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync}
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/**
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Disables the KVM system-time struct.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @returns VBox status code.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pVM Pointer to the VM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncVMMR3_INT_DECL(int) gimR3KvmDisableSystemTime(PVM pVM)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync{
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync TMR3CpuTickParavirtDisable(pVM);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync return VINF_SUCCESS;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync}
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync/**
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * Enables the KVM wall-clock structure.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @returns VBox status code.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param pVM Pointer to the VM.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param GCPhysWallClock Where the guest wall-clock structure is located.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @param uVersion The version (sequence number) value to use.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync *
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * @remarks Don't do any release assertions here, these can be triggered by
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * guest R0 code.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncVMMR3_INT_DECL(int) gimR3KvmEnableWallClock(PVM pVM, RTGCPHYS GCPhysWallClock, uint32_t uVersion)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync{
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync RTTIMESPEC TimeSpec;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync int32_t iSec;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync int32_t iNano;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync TMR3UtcNow(pVM, &TimeSpec);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync RTTimeSpecGetSecondsAndNano(&TimeSpec, &iSec, &iNano);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync GIMKVMWALLCLOCK WallClock;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync RT_ZERO(WallClock);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync WallClock.u32Version = uVersion;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync WallClock.u32Sec = iSec;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync WallClock.u32Nano = iNano;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync Assert(PGMPhysIsGCPhysNormal(pVM, GCPhysWallClock));
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync Assert(!(WallClock.u32Version & UINT32_C(1)));
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync int rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysWallClock, &WallClock, sizeof(GIMKVMWALLCLOCK));
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync if (RT_SUCCESS(rc))
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync LogRel(("GIM: KVM: Enabled wall-clock struct. at %#RGp - u32Sec=%u u32Nano=%u uVersion=%#RU32\n", GCPhysWallClock,
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync WallClock.u32Sec, WallClock.u32Nano, WallClock.u32Version));
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync else
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync LogRel(("GIM: KVM: Failed to write wall-clock struct. at %#RGp. rc=%Rrc\n", GCPhysWallClock, rc));
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync return rc;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync}
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync