GIMAllHv.cpp revision ce9f428fc2f581b4d8968d870967e259d9924d8d
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * GIM - Guest Interface Manager, Microsoft Hyper-V, All Contexts.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copyright (C) 2014 Oracle Corporation
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* Header Files *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte*******************************************************************************/
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Handles the Hyper-V hypercall.
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 ForteVMM_INT_DECL(int) GIMHvHypercall(PVMCPU pVCpu, PCPUMCTX pCtx)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!MSR_GIM_HV_HYPERCALL_IS_ENABLED(pVM->gim.s.u.Hv.u64HypercallMsr))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /** @todo Handle hypercalls. Fail for now */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Returns whether the guest has configured and enabled the use of Hyper-V's
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * hypercall interface.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @returns true if hypercalls are enabled, false otherwise.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pVCpu Pointer to the VMCPU.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn ForteVMM_INT_DECL(bool) GIMHvAreHypercallsEnabled(PVMCPU pVCpu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return MSR_GIM_HV_HYPERCALL_IS_ENABLED(pVCpu->CTX_SUFF(pVM)->gim.s.u.Hv.u64HypercallMsr);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Returns whether the guest has configured and enabled the use of Hyper-V's
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * paravirtualized TSC.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @returns true if paravirt. TSC is enabled, false otherwise.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pVM Pointer to the VM.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn ForteVMM_INT_DECL(bool) GIMHvIsParavirtTscEnabled(PVM pVM)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return MSR_GIM_HV_REF_TSC_IS_ENABLED(pVM->gim.s.u.Hv.u64TscPageMsr);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * MSR read handler for Hyper-V.
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 ForteVMM_INT_DECL(int) GIMHvReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
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 u64Tsc100Ns = u64TscHz / UINT64_C(10000000); /* 100 ns */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDMApicReadMSR(pVM, pVCpu->idCpu, 0x80, puValue);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDMApicReadMSR(pVM, pVCpu->idCpu, 0x0B, puValue);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDMApicReadMSR(pVM, pVCpu->idCpu, 0x30, puValue);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /** @todo Fix this later! Get the information from DevApic. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *puValue = UINT32_C(1000000000); /* TMCLOCK_FREQ_VIRTUAL */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte LogRel(("GIM: HyperV: Unknown/invalid RdMsr (%#x) -> #GP(0)\n", idMsr));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte LogFunc(("Unknown/invalid RdMsr (%#RX32) -> #GP(0)\n", idMsr));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * MSR write handler for Hyper-V.
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 ForteVMM_INT_DECL(int) GIMHvWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uRawValue)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDMApicWriteMSR(pVM, pVCpu->idCpu, 0x80, uRawValue);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDMApicWriteMSR(pVM, pVCpu->idCpu, 0x0B, uRawValue);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDMApicWriteMSR(pVM, pVCpu->idCpu, 0x30, uRawValue);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Disable the hypercall-page if 0 is written to this MSR. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pHv->u64HypercallMsr &= ~MSR_GIM_HV_HYPERCALL_ENABLE_BIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif /* !IN_RING3 */
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 /* 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 /* Is the guest disabling the hypercall-page? Allow it regardless of the Guest-OS Id Msr. */
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#endif /* !IN_RING3 */
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 /* Is the guest disabling the TSC-page? */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bool fEnable = RT_BOOL(uRawValue & MSR_GIM_HV_REF_TSC_ENABLE_BIT);
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#endif /* !IN_RING3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte LogRel(("GIM: HyperV: Reset initiated through MSR.\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* else: Ignore writes to other bits. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif /* !IN_RING3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MSR_GIM_HV_TIME_REF_COUNT: /* Read-only MSRs. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte LogFunc(("WrMsr on read-only MSR %#RX32 -> #GP(0)\n", idMsr));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte LogRel(("GIM: HyperV: Unknown/invalid WrMsr (%#x,%#x`%08x) -> #GP(0)\n", idMsr, uRawValue & UINT64_C(0xffffffff00000000),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte LogFunc(("Unknown/invalid WrMsr (%#RX32,%#RX64) -> #GP(0)\n", idMsr, uRawValue));