GIMAllHv.cpp revision ce9f428fc2f581b4d8968d870967e259d9924d8d
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* $Id$ */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/** @file
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * GIM - Guest Interface Manager, Microsoft Hyper-V, All Contexts.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copyright (C) 2014 Oracle Corporation
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This file is part of VirtualBox Open Source Edition (OSE), as
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * available from http://www.virtualbox.org. This file is free software;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * you can redistribute it and/or modify it under the terms of the GNU
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * General Public License (GPL) as published by the Free Software
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Foundation, in version 2 as it comes in the "COPYING" file of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*******************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte* Header Files *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte*******************************************************************************/
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define LOG_GROUP LOG_GROUP_GIM
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include "GIMHvInternal.h"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include "GIMInternal.h"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <VBox/err.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <VBox/vmm/hm.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <VBox/vmm/tm.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <VBox/vmm/vm.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <VBox/vmm/pgm.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <VBox/vmm/pdmdev.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <VBox/vmm/pdmapi.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <iprt/asm-amd64-x86.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <iprt/spinlock.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Handles the Hyper-V hypercall.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @returns VBox status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pVCpu Pointer to the VMCPU.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pCtx Pointer to the guest-CPU context.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn ForteVMM_INT_DECL(int) GIMHvHypercall(PVMCPU pVCpu, PCPUMCTX pCtx)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PVM pVM = pVCpu->CTX_SUFF(pVM);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!MSR_GIM_HV_HYPERCALL_IS_ENABLED(pVM->gim.s.u.Hv.u64HypercallMsr))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VERR_GIM_HYPERCALLS_NOT_ENABLED;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /** @todo Handle hypercalls. Fail for now */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VERR_GIM_IPE_3;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Returns whether the guest has configured and enabled the use of Hyper-V's
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * hypercall interface.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @returns true if hypercalls are enabled, false otherwise.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pVCpu Pointer to the VMCPU.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn ForteVMM_INT_DECL(bool) GIMHvAreHypercallsEnabled(PVMCPU pVCpu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return MSR_GIM_HV_HYPERCALL_IS_ENABLED(pVCpu->CTX_SUFF(pVM)->gim.s.u.Hv.u64HypercallMsr);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Returns whether the guest has configured and enabled the use of Hyper-V's
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * paravirtualized TSC.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @returns true if paravirt. TSC is enabled, false otherwise.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pVM Pointer to the VM.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn ForteVMM_INT_DECL(bool) GIMHvIsParavirtTscEnabled(PVM pVM)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return MSR_GIM_HV_REF_TSC_IS_ENABLED(pVM->gim.s.u.Hv.u64TscPageMsr);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * MSR read handler for Hyper-V.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @returns VBox status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pVCpu Pointer to the VMCPU.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param idMsr The MSR being read.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pRange The range this MSR belongs to.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param puValue Where to store the MSR value read.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn ForteVMM_INT_DECL(int) GIMHvReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte NOREF(pRange);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PVM pVM = pVCpu->CTX_SUFF(pVM);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PGIMHV pHv = &pVM->gim.s.u.Hv;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (idMsr)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_TIME_REF_COUNT:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /** @todo r=ramshankar: Shouldn't we add the TSC offset here? */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Hyper-V reports the time in 100 ns units (10 MHz). */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t u64Tsc = TMCpuTickGet(pVCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t u64TscHz = TMCpuTicksPerSecond(pVM);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t u64Tsc100Ns = u64TscHz / UINT64_C(10000000); /* 100 ns */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *puValue = (u64Tsc / u64Tsc100Ns);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_VP_INDEX:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *puValue = pVCpu->idCpu;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_TPR:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDMApicReadMSR(pVM, pVCpu->idCpu, 0x80, puValue);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_EOI:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDMApicReadMSR(pVM, pVCpu->idCpu, 0x0B, puValue);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_ICR:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDMApicReadMSR(pVM, pVCpu->idCpu, 0x30, puValue);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_GUEST_OS_ID:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *puValue = pHv->u64GuestOsIdMsr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_HYPERCALL:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *puValue = pHv->u64HypercallMsr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_REF_TSC:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *puValue = pHv->u64TscPageMsr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_TSC_FREQ:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *puValue = TMCpuTicksPerSecond(pVM);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_APIC_FREQ:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /** @todo Fix this later! Get the information from DevApic. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *puValue = UINT32_C(1000000000); /* TMCLOCK_FREQ_VIRTUAL */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_RESET:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *puValue = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#ifdef IN_RING3
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte static uint32_t s_cTimes = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (s_cTimes++ < 20)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte LogRel(("GIM: HyperV: Unknown/invalid RdMsr (%#x) -> #GP(0)\n", idMsr));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte LogFunc(("Unknown/invalid RdMsr (%#RX32) -> #GP(0)\n", idMsr));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VERR_CPUM_RAISE_GP_0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * MSR write handler for Hyper-V.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @returns VBox status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pVCpu Pointer to the VMCPU.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param idMsr The MSR being written.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pRange The range this MSR belongs to.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param uRawValue The raw value with the ignored bits not masked.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn ForteVMM_INT_DECL(int) GIMHvWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uRawValue)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte NOREF(pRange);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PVM pVM = pVCpu->CTX_SUFF(pVM);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PGIMHV pHv = &pVM->gim.s.u.Hv;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (idMsr)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_TPR:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDMApicWriteMSR(pVM, pVCpu->idCpu, 0x80, uRawValue);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_EOI:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDMApicWriteMSR(pVM, pVCpu->idCpu, 0x0B, uRawValue);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_ICR:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDMApicWriteMSR(pVM, pVCpu->idCpu, 0x30, uRawValue);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_GUEST_OS_ID:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#ifndef IN_RING3
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VERR_EM_INTERPRETER;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Disable the hypercall-page if 0 is written to this MSR. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!uRawValue)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte GIMR3HvDisableHypercallPage(pVM);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pHv->u64HypercallMsr &= ~MSR_GIM_HV_HYPERCALL_ENABLE_BIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pHv->u64GuestOsIdMsr = uRawValue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif /* !IN_RING3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_HYPERCALL:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#ifndef IN_RING3
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VERR_EM_INTERPRETER;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#else /* IN_RING3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* First, update all but the hypercall enable bit. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pHv->u64HypercallMsr = (uRawValue & ~MSR_GIM_HV_HYPERCALL_ENABLE_BIT);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Hypercalls can only be enabled when the guest has set the Guest-OS Id Msr. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bool fEnable = RT_BOOL(uRawValue & MSR_GIM_HV_HYPERCALL_ENABLE_BIT);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ( fEnable
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte && !pHv->u64GuestOsIdMsr)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Is the guest disabling the hypercall-page? Allow it regardless of the Guest-OS Id Msr. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!fEnable)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte GIMR3HvDisableHypercallPage(pVM);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pHv->u64HypercallMsr = uRawValue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Enable the hypercall-page. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RTGCPHYS GCPhysHypercallPage = MSR_GIM_HV_HYPERCALL_GUEST_PFN(uRawValue) << PAGE_SHIFT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int rc = GIMR3HvEnableHypercallPage(pVM, GCPhysHypercallPage);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (RT_SUCCESS(rc))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pHv->u64HypercallMsr = uRawValue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VERR_CPUM_RAISE_GP_0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif /* !IN_RING3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_REF_TSC:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#ifndef IN_RING3
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VERR_EM_INTERPRETER;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#else /* IN_RING3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* First, update all but the TSC-page enable bit. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pHv->u64TscPageMsr = (uRawValue & ~MSR_GIM_HV_REF_TSC_ENABLE_BIT);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Is the guest disabling the TSC-page? */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bool fEnable = RT_BOOL(uRawValue & MSR_GIM_HV_REF_TSC_ENABLE_BIT);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!fEnable)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte GIMR3HvDisableTscPage(pVM);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pHv->u64TscPageMsr = uRawValue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Enable the TSC-page. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RTGCPHYS GCPhysTscPage = MSR_GIM_HV_REF_TSC_GUEST_PFN(uRawValue) << PAGE_SHIFT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int rc = GIMR3HvEnableTscPage(pVM, GCPhysTscPage, false /* fUseThisTscSequence */, 0 /* uTscSequence */);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (RT_SUCCESS(rc))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pHv->u64TscPageMsr = uRawValue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VERR_CPUM_RAISE_GP_0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif /* !IN_RING3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_RESET:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#ifndef IN_RING3
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VERR_EM_INTERPRETER;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (MSR_GIM_HV_RESET_IS_SET(uRawValue))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte LogRel(("GIM: HyperV: Reset initiated through MSR.\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int rc = PDMDevHlpVMReset(pVM->gim.s.pDevInsR3);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte AssertRC(rc);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* else: Ignore writes to other bits. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif /* !IN_RING3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_TIME_REF_COUNT: /* Read-only MSRs. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_VP_INDEX:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_TSC_FREQ:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_APIC_FREQ:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte LogFunc(("WrMsr on read-only MSR %#RX32 -> #GP(0)\n", idMsr));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VERR_CPUM_RAISE_GP_0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#ifdef IN_RING3
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte static uint32_t s_cTimes = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (s_cTimes++ < 20)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte LogRel(("GIM: HyperV: Unknown/invalid WrMsr (%#x,%#x`%08x) -> #GP(0)\n", idMsr, uRawValue & UINT64_C(0xffffffff00000000),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uRawValue & UINT64_C(0xffffffff)));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte LogFunc(("Unknown/invalid WrMsr (%#RX32,%#RX64) -> #GP(0)\n", idMsr, uRawValue));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VERR_CPUM_RAISE_GP_0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte