GIMAll.cpp revision 6d0dfca130b3267e60e6dcb6f8cea0487534680a
236b2935f217749893b7034e59da3e3568928acevboxsync/* $Id$ */
236b2935f217749893b7034e59da3e3568928acevboxsync/** @file
236b2935f217749893b7034e59da3e3568928acevboxsync * GIM - Guest Interface Manager - All Contexts.
236b2935f217749893b7034e59da3e3568928acevboxsync */
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync/*
236b2935f217749893b7034e59da3e3568928acevboxsync * Copyright (C) 2014 Oracle Corporation
236b2935f217749893b7034e59da3e3568928acevboxsync *
236b2935f217749893b7034e59da3e3568928acevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
236b2935f217749893b7034e59da3e3568928acevboxsync * available from http://www.virtualbox.org. This file is free software;
236b2935f217749893b7034e59da3e3568928acevboxsync * you can redistribute it and/or modify it under the terms of the GNU
236b2935f217749893b7034e59da3e3568928acevboxsync * General Public License (GPL) as published by the Free Software
236b2935f217749893b7034e59da3e3568928acevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
236b2935f217749893b7034e59da3e3568928acevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
236b2935f217749893b7034e59da3e3568928acevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
236b2935f217749893b7034e59da3e3568928acevboxsync */
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync/*******************************************************************************
236b2935f217749893b7034e59da3e3568928acevboxsync* Header Files *
236b2935f217749893b7034e59da3e3568928acevboxsync*******************************************************************************/
236b2935f217749893b7034e59da3e3568928acevboxsync#define LOG_GROUP LOG_GROUP_GIM
236b2935f217749893b7034e59da3e3568928acevboxsync#include "GIMInternal.h"
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync#include <VBox/err.h>
236b2935f217749893b7034e59da3e3568928acevboxsync#include <VBox/vmm/vm.h>
236b2935f217749893b7034e59da3e3568928acevboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync/* Include all the providers. */
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync#include "GIMHvInternal.h"
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync#include "GIMMinimalInternal.h"
236b2935f217749893b7034e59da3e3568928acevboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync/**
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * Checks whether GIM is being used by this VM.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync *
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @retval @c true if used.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @retval @c false if no GIM provider ("none") is used.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync *
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @param pVM Pointer to the VM.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync */
236b2935f217749893b7034e59da3e3568928acevboxsyncVMMDECL(bool) GIMIsEnabled(PVM pVM)
236b2935f217749893b7034e59da3e3568928acevboxsync{
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync return pVM->gim.s.enmProviderId != GIMPROVIDERID_NONE;
236b2935f217749893b7034e59da3e3568928acevboxsync}
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync/**
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Gets the GIM provider configured for this VM.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync *
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @returns The GIM provider Id.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pVM Pointer to the VM.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync */
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncVMMDECL(GIMPROVIDERID) GIMGetProvider(PVM pVM)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync{
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync return pVM->gim.s.enmProviderId;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync}
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync/**
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync * Returns whether the guest has configured and enabled calls to the hypervisor.
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync *
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync * @returns true if hypercalls are enabled and usable, false otherwise.
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync * @param pVCpu Pointer to the VMCPU.
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync */
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsyncVMM_INT_DECL(bool) GIMAreHypercallsEnabled(PVMCPU pVCpu)
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync{
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync PVM pVM = pVCpu->CTX_SUFF(pVM);
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync if (!GIMIsEnabled(pVM))
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync return false;
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync switch (pVM->gim.s.enmProviderId)
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync {
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync case GIMPROVIDERID_HYPERV:
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync return GIMHvAreHypercallsEnabled(pVCpu);
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync default:
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync return false;
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync }
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync}
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync/**
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * Implements a GIM hypercall with the provider configured for the VM.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync *
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @returns VBox status code.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @param pVCpu Pointer to the VMCPU.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @param pCtx Pointer to the guest-CPU context.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync */
236b2935f217749893b7034e59da3e3568928acevboxsyncVMM_INT_DECL(int) GIMHypercall(PVMCPU pVCpu, PCPUMCTX pCtx)
236b2935f217749893b7034e59da3e3568928acevboxsync{
236b2935f217749893b7034e59da3e3568928acevboxsync PVM pVM = pVCpu->CTX_SUFF(pVM);
236b2935f217749893b7034e59da3e3568928acevboxsync VMCPU_ASSERT_EMT(pVCpu);
236b2935f217749893b7034e59da3e3568928acevboxsync
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync if (RT_UNLIKELY(!GIMIsEnabled(pVM)))
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync return VERR_GIM_NOT_ENABLED;
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync switch (pVM->gim.s.enmProviderId)
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync {
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync case GIMPROVIDERID_HYPERV:
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync return GIMHvHypercall(pVCpu, pCtx);
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync default:
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync AssertMsgFailed(("GIMHypercall: for unknown provider %u\n", pVM->gim.s.enmProviderId));
157093a77f2752732368338110cb50fa6cd7717fvboxsync return VERR_GIM_IPE_3;
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync }
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync}
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync/**
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync * Returns whether the guest has configured and setup the use of paravirtualized
6d0dfca130b3267e60e6dcb6f8cea0487534680avboxsync * TSC.
6d0dfca130b3267e60e6dcb6f8cea0487534680avboxsync *
6d0dfca130b3267e60e6dcb6f8cea0487534680avboxsync * Paravirtualized TSCs are per-VM and the rest of the execution engine logic
6d0dfca130b3267e60e6dcb6f8cea0487534680avboxsync * relies on that.
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync *
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync * @returns true if enabled and usable, false otherwise.
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync * @param pVM Pointer to the VM.
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsync */
ce9f428fc2f581b4d8968d870967e259d9924d8dvboxsyncVMM_INT_DECL(bool) GIMIsParavirtTscEnabled(PVM pVM)
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync{
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync switch (pVM->gim.s.enmProviderId)
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync {
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync case GIMPROVIDERID_HYPERV:
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync return GIMHvIsParavirtTscEnabled(pVM);
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync default:
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync break;
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync }
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync return false;
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync}
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync/**
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * Invokes the read-MSR handler for the GIM provider configured for the VM.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync *
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @returns VBox status code.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @param pVCpu Pointer to the VMCPU.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @param idMsr The MSR to read.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @param pRange The range this MSR belongs to.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @param puValue Where to store the MSR value read.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync */
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsyncVMM_INT_DECL(int) GIMReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync{
bc5cd42756b3f98351040bbfccc08dd9bacd103avboxsync Assert(pVCpu);
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync PVM pVM = pVCpu->CTX_SUFF(pVM);
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync Assert(GIMIsEnabled(pVM));
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync VMCPU_ASSERT_EMT(pVCpu);
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync switch (pVM->gim.s.enmProviderId)
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync {
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync case GIMPROVIDERID_HYPERV:
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync return GIMHvReadMsr(pVCpu, idMsr, pRange, puValue);
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync default:
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync AssertMsgFailed(("GIMReadMsr: for unknown provider %u idMsr=%#RX32 -> #GP(0)", pVM->gim.s.enmProviderId, idMsr));
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync return VERR_CPUM_RAISE_GP_0;
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync }
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync}
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync/**
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * Invokes the write-MSR handler for the GIM provider configured for the VM.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync *
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @returns VBox status code.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @param pVCpu Pointer to the VMCPU.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @param idMsr The MSR to write.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @param pRange The range this MSR belongs to.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @param uValue The value to set, ignored bits masked.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * @param uRawValue The raw value with the ignored bits not masked.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync */
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsyncVMM_INT_DECL(int) GIMWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync{
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync AssertPtr(pVCpu);
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync NOREF(uValue);
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync PVM pVM = pVCpu->CTX_SUFF(pVM);
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync Assert(GIMIsEnabled(pVM));
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync VMCPU_ASSERT_EMT(pVCpu);
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync switch (pVM->gim.s.enmProviderId)
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync {
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync case GIMPROVIDERID_HYPERV:
eca46116c06b850c8c6be84678ba1f9dbdb3f9ddvboxsync return GIMHvWriteMsr(pVCpu, idMsr, pRange, uRawValue);
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync default:
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync AssertMsgFailed(("GIMWriteMsr: for unknown provider %u idMsr=%#RX32 -> #GP(0)", pVM->gim.s.enmProviderId, idMsr));
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync return VERR_CPUM_RAISE_GP_0;
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync }
236b2935f217749893b7034e59da3e3568928acevboxsync}
236b2935f217749893b7034e59da3e3568928acevboxsync