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