コード例 #1
0
/**
 * Hyper-V state-save operation.
 *
 * @returns VBox status code.
 * @param   pVM     Pointer to the VM.
 * @param   pSSM    Pointer to the SSM handle.
 */
VMMR3_INT_DECL(int) gimR3HvSave(PVM pVM, PSSMHANDLE pSSM)
{
    PCGIMHV pcHv = &pVM->gim.s.u.Hv;

    /*
     * Save the Hyper-V SSM version.
     */
    SSMR3PutU32(pSSM, GIM_HV_SAVED_STATE_VERSION);

    /*
     * Save per-VM MSRs.
     */
    SSMR3PutU64(pSSM, pcHv->u64GuestOsIdMsr);
    SSMR3PutU64(pSSM, pcHv->u64HypercallMsr);
    SSMR3PutU64(pSSM, pcHv->u64TscPageMsr);

    /*
     * Save Hyper-V features / capabilities.
     */
    SSMR3PutU32(pSSM, pcHv->uBaseFeat);
    SSMR3PutU32(pSSM, pcHv->uPartFlags);
    SSMR3PutU32(pSSM, pcHv->uPowMgmtFeat);
    SSMR3PutU32(pSSM, pcHv->uMiscFeat);
    SSMR3PutU32(pSSM, pcHv->uHyperHints);
    SSMR3PutU32(pSSM, pcHv->uHyperCaps);

    /*
     * Save the Hypercall region.
     */
    PCGIMMMIO2REGION pcRegion = &pcHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX];
    SSMR3PutU8(pSSM,     pcRegion->iRegion);
    SSMR3PutBool(pSSM,   pcRegion->fRCMapping);
    SSMR3PutU32(pSSM,    pcRegion->cbRegion);
    SSMR3PutGCPhys(pSSM, pcRegion->GCPhysPage);
    SSMR3PutStrZ(pSSM,   pcRegion->szDescription);

    /*
     * Save the reference TSC region.
     */
    pcRegion = &pcHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX];
    SSMR3PutU8(pSSM,     pcRegion->iRegion);
    SSMR3PutBool(pSSM,   pcRegion->fRCMapping);
    SSMR3PutU32(pSSM,    pcRegion->cbRegion);
    SSMR3PutGCPhys(pSSM, pcRegion->GCPhysPage);
    SSMR3PutStrZ(pSSM,   pcRegion->szDescription);
    /* Save the TSC sequence so we can bump it on restore (as the CPU frequency/offset may change). */
    uint32_t uTscSequence = 0;
    if (   pcRegion->fMapped
        && MSR_GIM_HV_REF_TSC_IS_ENABLED(pcHv->u64TscPageMsr))
    {
        PCGIMHVREFTSC pcRefTsc = (PCGIMHVREFTSC)pcRegion->pvPageR3;
        uTscSequence = pcRefTsc->u32TscSequence;
    }

    return SSMR3PutU32(pSSM, uTscSequence);
}
コード例 #2
0
/**
 * Updates Hyper-V's reference TSC page.
 *
 * @returns VBox status code.
 * @param   pVM         Pointer to the VM.
 * @param   u64Offset   The computed TSC offset.
 * @thread  EMT.
 */
VMM_INT_DECL(int) gimR0HvUpdateParavirtTsc(PVM pVM, uint64_t u64Offset)
{
    Assert(GIMIsEnabled(pVM));
    bool fHvTscEnabled = MSR_GIM_HV_REF_TSC_IS_ENABLED(pVM->gim.s.u.Hv.u64TscPageMsr);
    if (RT_UNLIKELY(!fHvTscEnabled))
        return VERR_GIM_PVTSC_NOT_ENABLED;

    PCGIMHV          pcHv     = &pVM->gim.s.u.Hv;
    PCGIMMMIO2REGION pcRegion = &pcHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX];
    PGIMHVREFTSC     pRefTsc  = (PGIMHVREFTSC)pcRegion->CTX_SUFF(pvPage);
    Assert(pRefTsc);

    /*
     * Hyper-V reports the reference time in 100 nanosecond units.
     */
    uint64_t u64Tsc100Ns = TMCpuTicksPerSecond(pVM) / RT_NS_10MS;
    int64_t i64TscOffset = (int64_t)u64Offset / u64Tsc100Ns;

    /*
     * The TSC page can be simulatenously read by other VCPUs in the guest. The
     * spinlock is only for protecting simultaneous hypervisor writes from other
     * EMTs.
     */
    RTSpinlockAcquire(pcHv->hSpinlockR0);
    if (pRefTsc->i64TscOffset != i64TscOffset)
    {
        if (pRefTsc->u32TscSequence < UINT32_C(0xfffffffe))
            ASMAtomicIncU32(&pRefTsc->u32TscSequence);
        else
            ASMAtomicWriteU32(&pRefTsc->u32TscSequence, 1);
        ASMAtomicWriteS64(&pRefTsc->i64TscOffset, i64TscOffset);
    }
    RTSpinlockRelease(pcHv->hSpinlockR0);

    Assert(pRefTsc->u32TscSequence != 0);
    Assert(pRefTsc->u32TscSequence != UINT32_C(0xffffffff));
    return VINF_SUCCESS;
}
コード例 #3
0
/**
 * 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;
}
コード例 #4
0
ファイル: GIMAllHv.cpp プロジェクト: rickysarraf/virtualbox
/**
 * Returns whether the guest has configured and enabled the use of Hyper-V's
 * paravirtualized TSC.
 *
 * @returns true if paravirt. TSC is enabled, false otherwise.
 * @param   pVM     Pointer to the VM.
 */
VMM_INT_DECL(bool) gimHvIsParavirtTscEnabled(PVM pVM)
{
    return MSR_GIM_HV_REF_TSC_IS_ENABLED(pVM->gim.s.u.Hv.u64TscPageMsr);
}