157093a77f2752732368338110cb50fa6cd7717fvboxsync/* $Id$ */
157093a77f2752732368338110cb50fa6cd7717fvboxsync/** @file
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Guest Interface Manager (GIM), Hyper-V - Host Context Ring-0.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync/*
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Copyright (C) 2014 Oracle Corporation
157093a77f2752732368338110cb50fa6cd7717fvboxsync *
157093a77f2752732368338110cb50fa6cd7717fvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
157093a77f2752732368338110cb50fa6cd7717fvboxsync * available from http://www.virtualbox.org. This file is free software;
157093a77f2752732368338110cb50fa6cd7717fvboxsync * you can redistribute it and/or modify it under the terms of the GNU
157093a77f2752732368338110cb50fa6cd7717fvboxsync * General Public License (GPL) as published by the Free Software
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
157093a77f2752732368338110cb50fa6cd7717fvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
157093a77f2752732368338110cb50fa6cd7717fvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync/*******************************************************************************
157093a77f2752732368338110cb50fa6cd7717fvboxsync* Header Files *
157093a77f2752732368338110cb50fa6cd7717fvboxsync*******************************************************************************/
157093a77f2752732368338110cb50fa6cd7717fvboxsync#define LOG_GROUP LOG_GROUP_GIM
157093a77f2752732368338110cb50fa6cd7717fvboxsync#include "GIMInternal.h"
157093a77f2752732368338110cb50fa6cd7717fvboxsync#include "GIMHvInternal.h"
157093a77f2752732368338110cb50fa6cd7717fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync#include <VBox/err.h>
157093a77f2752732368338110cb50fa6cd7717fvboxsync#include <VBox/vmm/gim.h>
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync#include <VBox/vmm/tm.h>
157093a77f2752732368338110cb50fa6cd7717fvboxsync#include <VBox/vmm/vm.h>
157093a77f2752732368338110cb50fa6cd7717fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync#include <iprt/spinlock.h>
157093a77f2752732368338110cb50fa6cd7717fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync#if 0
157093a77f2752732368338110cb50fa6cd7717fvboxsync/**
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Allocates and maps one physically contiguous page. The allocated page is
157093a77f2752732368338110cb50fa6cd7717fvboxsync * zero'd out.
157093a77f2752732368338110cb50fa6cd7717fvboxsync *
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @returns IPRT status code.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pMemObj Pointer to the ring-0 memory object.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param ppVirt Where to store the virtual address of the
157093a77f2752732368338110cb50fa6cd7717fvboxsync * allocation.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pPhys Where to store the physical address of the
157093a77f2752732368338110cb50fa6cd7717fvboxsync * allocation.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
157093a77f2752732368338110cb50fa6cd7717fvboxsyncstatic int gimR0HvPageAllocZ(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
157093a77f2752732368338110cb50fa6cd7717fvboxsync{
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertPtr(pMemObj);
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertPtr(ppVirt);
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertPtr(pHCPhys);
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync int rc = RTR0MemObjAllocCont(pMemObj, PAGE_SIZE, false /* fExecutable */);
157093a77f2752732368338110cb50fa6cd7717fvboxsync if (RT_FAILURE(rc))
157093a77f2752732368338110cb50fa6cd7717fvboxsync return rc;
157093a77f2752732368338110cb50fa6cd7717fvboxsync *ppVirt = RTR0MemObjAddress(*pMemObj);
157093a77f2752732368338110cb50fa6cd7717fvboxsync *pHCPhys = RTR0MemObjGetPagePhysAddr(*pMemObj, 0 /* iPage */);
157093a77f2752732368338110cb50fa6cd7717fvboxsync ASMMemZero32(*ppVirt, PAGE_SIZE);
157093a77f2752732368338110cb50fa6cd7717fvboxsync return VINF_SUCCESS;
157093a77f2752732368338110cb50fa6cd7717fvboxsync}
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync/**
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Frees and unmaps an allocated physical page.
157093a77f2752732368338110cb50fa6cd7717fvboxsync *
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pMemObj Pointer to the ring-0 memory object.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param ppVirt Where to re-initialize the virtual address of
157093a77f2752732368338110cb50fa6cd7717fvboxsync * allocation as 0.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pHCPhys Where to re-initialize the physical address of the
157093a77f2752732368338110cb50fa6cd7717fvboxsync * allocation as 0.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
157093a77f2752732368338110cb50fa6cd7717fvboxsyncstatic void gimR0HvPageFree(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
157093a77f2752732368338110cb50fa6cd7717fvboxsync{
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertPtr(pMemObj);
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertPtr(ppVirt);
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertPtr(pHCPhys);
157093a77f2752732368338110cb50fa6cd7717fvboxsync if (*pMemObj != NIL_RTR0MEMOBJ)
157093a77f2752732368338110cb50fa6cd7717fvboxsync {
157093a77f2752732368338110cb50fa6cd7717fvboxsync int rc = RTR0MemObjFree(*pMemObj, true /* fFreeMappings */);
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertRC(rc);
157093a77f2752732368338110cb50fa6cd7717fvboxsync *pMemObj = NIL_RTR0MEMOBJ;
157093a77f2752732368338110cb50fa6cd7717fvboxsync *ppVirt = 0;
157093a77f2752732368338110cb50fa6cd7717fvboxsync *pHCPhys = 0;
157093a77f2752732368338110cb50fa6cd7717fvboxsync }
157093a77f2752732368338110cb50fa6cd7717fvboxsync}
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync#endif
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync/**
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Updates Hyper-V's reference TSC page.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync *
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @returns VBox status code.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pVM Pointer to the VM.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param u64Offset The computed TSC offset.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @thread EMT.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync */
d8744f4146c228198b84db51c7209a3175b25e07vboxsyncVMM_INT_DECL(int) gimR0HvUpdateParavirtTsc(PVM pVM, uint64_t u64Offset)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync{
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync Assert(GIMIsEnabled(pVM));
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync bool fHvTscEnabled = MSR_GIM_HV_REF_TSC_IS_ENABLED(pVM->gim.s.u.Hv.u64TscPageMsr);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync if (RT_UNLIKELY(!fHvTscEnabled))
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync return VERR_GIM_PVTSC_NOT_ENABLED;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync PCGIMHV pcHv = &pVM->gim.s.u.Hv;
d1bbcc83a0c9ccb22e216e9346143179b0c8a554vboxsync PCGIMMMIO2REGION pcRegion = &pcHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX];
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync PGIMHVREFTSC pRefTsc = (PGIMHVREFTSC)pcRegion->CTX_SUFF(pvPage);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync Assert(pRefTsc);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync /*
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync * Hyper-V reports the reference time in 100 nanosecond units.
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync */
63ff009f4d6033ac5e3557c9c5ec0329ed5c0a19vboxsync uint64_t u64Tsc100Ns = TMCpuTicksPerSecond(pVM) / RT_NS_10MS;
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync int64_t i64TscOffset = (int64_t)u64Offset / u64Tsc100Ns;
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync /*
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync * The TSC page can be simulatenously read by other VCPUs in the guest. The
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync * spinlock is only for protecting simultaneous hypervisor writes from other
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync * EMTs.
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync */
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync RTSpinlockAcquire(pcHv->hSpinlockR0);
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync if (pRefTsc->i64TscOffset != i64TscOffset)
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync {
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync if (pRefTsc->u32TscSequence < UINT32_C(0xfffffffe))
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync ASMAtomicIncU32(&pRefTsc->u32TscSequence);
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync else
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync ASMAtomicWriteU32(&pRefTsc->u32TscSequence, 1);
bc7fd0c97cf19d987daf12b1f4893bec2e2a7c96vboxsync ASMAtomicWriteS64(&pRefTsc->i64TscOffset, i64TscOffset);
59c7f47943ae42abc3d4e1c6d87b789b668b1260vboxsync }
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync RTSpinlockRelease(pcHv->hSpinlockR0);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync Assert(pRefTsc->u32TscSequence != 0);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync Assert(pRefTsc->u32TscSequence != UINT32_C(0xffffffff));
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync return VINF_SUCCESS;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync}
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync/**
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Does ring-0 per-VM GIM Hyper-V initialization.
157093a77f2752732368338110cb50fa6cd7717fvboxsync *
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @returns VBox status code.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pVM Pointer to the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
d8744f4146c228198b84db51c7209a3175b25e07vboxsyncVMMR0_INT_DECL(int) gimR0HvInitVM(PVM pVM)
157093a77f2752732368338110cb50fa6cd7717fvboxsync{
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertPtr(pVM);
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(GIMIsEnabled(pVM));
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync PGIMHV pHv = &pVM->gim.s.u.Hv;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync Assert(pHv->hSpinlockR0 == NIL_RTSPINLOCK);
157093a77f2752732368338110cb50fa6cd7717fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync int rc = RTSpinlockCreate(&pHv->hSpinlockR0, RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, "Hyper-V");
157093a77f2752732368338110cb50fa6cd7717fvboxsync return rc;
157093a77f2752732368338110cb50fa6cd7717fvboxsync}
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync/**
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Does ring-0 per-VM GIM Hyper-V termination.
157093a77f2752732368338110cb50fa6cd7717fvboxsync *
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @returns VBox status code.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pVM Pointer to the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
d8744f4146c228198b84db51c7209a3175b25e07vboxsyncVMMR0_INT_DECL(int) gimR0HvTermVM(PVM pVM)
157093a77f2752732368338110cb50fa6cd7717fvboxsync{
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertPtr(pVM);
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(GIMIsEnabled(pVM));
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync PGIMHV pHv = &pVM->gim.s.u.Hv;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync RTSpinlockDestroy(pHv->hSpinlockR0);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync pHv->hSpinlockR0 = NIL_RTSPINLOCK;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync return VINF_SUCCESS;
157093a77f2752732368338110cb50fa6cd7717fvboxsync}
157093a77f2752732368338110cb50fa6cd7717fvboxsync