Ejemplo n.º 1
0
/**
 * KVM 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) gimR3KvmLoad(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion)
{
    /*
     * Load the KVM SSM version first.
     */
    uint32_t uKvmSavedStatVersion;
    int rc = SSMR3GetU32(pSSM, &uKvmSavedStatVersion);
    AssertRCReturn(rc, rc);
    if (uKvmSavedStatVersion != GIM_KVM_SAVED_STATE_VERSION)
        return SSMR3SetLoadError(pSSM, VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION, RT_SRC_POS,
                                 N_("Unsupported KVM saved-state version %u (expected %u)."), uKvmSavedStatVersion,
                                 GIM_KVM_SAVED_STATE_VERSION);

    /*
     * Update the TSC frequency from TM.
     */
    PGIMKVM pKvm = &pVM->gim.s.u.Kvm;
    pKvm->cTscTicksPerSecond = TMCpuTicksPerSecond(pVM);

    /*
     * Load per-VCPU data.
     */
    for (uint32_t i = 0; i < pVM->cCpus; i++)
    {
        PVMCPU     pVCpu   = &pVM->aCpus[i];
        PGIMKVMCPU pKvmCpu = &pVCpu->gim.s.u.KvmCpu;

        uint8_t fSystemTimeFlags = 0;
        SSMR3GetU64(pSSM, &pKvmCpu->u64SystemTimeMsr);
        SSMR3GetU64(pSSM, &pKvmCpu->uTsc);
        SSMR3GetU64(pSSM, &pKvmCpu->uVirtNanoTS);
        SSMR3GetGCPhys(pSSM, &pKvmCpu->GCPhysSystemTime);
        SSMR3GetU32(pSSM, &pKvmCpu->u32SystemTimeVersion);
        rc = SSMR3GetU8(pSSM, &pKvmCpu->fSystemTimeFlags);
        AssertRCReturn(rc, rc);

        /* Enable the system-time struct. if necessary. */
        /** @todo update guest struct only if cTscTicksPerSecond doesn't match host
         *        anymore. */
        if (MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(pKvmCpu->u64SystemTimeMsr))
        {
            Assert(!TMVirtualIsTicking(pVM));       /* paranoia. */
            Assert(!TMCpuTickIsTicking(pVCpu));
            rc = gimR3KvmEnableSystemTime(pVM, pVCpu);
            AssertRCReturn(rc, rc);
        }
    }

    /*
     * Load per-VM data.
     */
    SSMR3GetU64(pSSM, &pKvm->u64WallClockMsr);
    rc = SSMR3GetU32(pSSM, &pKvm->uBaseFeat);
    AssertRCReturn(rc, rc);

    return VINF_SUCCESS;
}
/**
 * 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;
}