/** * Handles the Hyper-V hypercall. * * @returns VBox status code. * @param pVCpu Pointer to the VMCPU. * @param pCtx Pointer to the guest-CPU context. */ VMM_INT_DECL(int) gimHvHypercall(PVMCPU pVCpu, PCPUMCTX pCtx) { PVM pVM = pVCpu->CTX_SUFF(pVM); if (!MSR_GIM_HV_HYPERCALL_IS_ENABLED(pVM->gim.s.u.Hv.u64HypercallMsr)) return VERR_GIM_HYPERCALLS_NOT_ENABLED; /** @todo Handle hypercalls. Fail for now */ return VERR_GIM_IPE_3; }
/** * Hyper-V state-load operation, final pass. * * @returns VBox status code. * @param pVM Pointer to the VM. * @param pSSM Pointer to the SSM handle. * @param uSSMVersion The GIM saved-state version. */ VMMR3_INT_DECL(int) gimR3HvLoad(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion) { PGIMHV pHv = &pVM->gim.s.u.Hv; /* * Load the Hyper-V SSM version first. */ uint32_t uHvSavedStatVersion; int rc = SSMR3GetU32(pSSM, &uHvSavedStatVersion); AssertRCReturn(rc, rc); if (uHvSavedStatVersion != GIM_HV_SAVED_STATE_VERSION) return SSMR3SetLoadError(pSSM, VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION, RT_SRC_POS, N_("Unsupported Hyper-V saved-state version %u (expected %u)."), uHvSavedStatVersion, GIM_HV_SAVED_STATE_VERSION); /* * Load per-VM MSRs. */ SSMR3GetU64(pSSM, &pHv->u64GuestOsIdMsr); SSMR3GetU64(pSSM, &pHv->u64HypercallMsr); SSMR3GetU64(pSSM, &pHv->u64TscPageMsr); /* * Load Hyper-V features / capabilities. */ SSMR3GetU32(pSSM, &pHv->uBaseFeat); SSMR3GetU32(pSSM, &pHv->uPartFlags); SSMR3GetU32(pSSM, &pHv->uPowMgmtFeat); SSMR3GetU32(pSSM, &pHv->uMiscFeat); SSMR3GetU32(pSSM, &pHv->uHyperHints); SSMR3GetU32(pSSM, &pHv->uHyperCaps); /* * Load and enable the Hypercall region. */ PGIMMMIO2REGION pRegion = &pHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX]; SSMR3GetU8(pSSM, &pRegion->iRegion); SSMR3GetBool(pSSM, &pRegion->fRCMapping); SSMR3GetU32(pSSM, &pRegion->cbRegion); SSMR3GetGCPhys(pSSM, &pRegion->GCPhysPage); rc = SSMR3GetStrZ(pSSM, pRegion->szDescription, sizeof(pRegion->szDescription)); AssertRCReturn(rc, rc); if (MSR_GIM_HV_HYPERCALL_IS_ENABLED(pHv->u64HypercallMsr)) { Assert(pRegion->GCPhysPage != NIL_RTGCPHYS); if (RT_LIKELY(pRegion->fRegistered)) { rc = gimR3HvEnableHypercallPage(pVM, pRegion->GCPhysPage); if (RT_FAILURE(rc)) return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Failed to enable the hypercall page. GCPhys=%#RGp rc=%Rrc"), pRegion->GCPhysPage, rc); } else return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Hypercall MMIO2 region not registered. Missing GIM device?!")); } /* * Load and enable the reference TSC region. */ uint32_t uTscSequence; pRegion = &pHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX]; SSMR3GetU8(pSSM, &pRegion->iRegion); SSMR3GetBool(pSSM, &pRegion->fRCMapping); SSMR3GetU32(pSSM, &pRegion->cbRegion); SSMR3GetGCPhys(pSSM, &pRegion->GCPhysPage); SSMR3GetStrZ(pSSM, pRegion->szDescription, sizeof(pRegion->szDescription)); rc = SSMR3GetU32(pSSM, &uTscSequence); AssertRCReturn(rc, rc); if (MSR_GIM_HV_REF_TSC_IS_ENABLED(pHv->u64TscPageMsr)) { Assert(pRegion->GCPhysPage != NIL_RTGCPHYS); if (pRegion->fRegistered) { rc = gimR3HvEnableTscPage(pVM, pRegion->GCPhysPage, true /* fUseThisTscSeq */, uTscSequence); if (RT_FAILURE(rc)) return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Failed to enable the TSC page. GCPhys=%#RGp rc=%Rrc"), pRegion->GCPhysPage, rc); } else return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("TSC-page MMIO2 region not registered. Missing GIM device?!")); } return rc; }
/** * Returns whether the guest has configured and enabled the use of Hyper-V's * hypercall interface. * * @returns true if hypercalls are enabled, false otherwise. * @param pVCpu Pointer to the VMCPU. */ VMM_INT_DECL(bool) gimHvAreHypercallsEnabled(PVMCPU pVCpu) { return MSR_GIM_HV_HYPERCALL_IS_ENABLED(pVCpu->CTX_SUFF(pVM)->gim.s.u.Hv.u64HypercallMsr); }