/** * 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); }
/** * KVM state-save operation. * * @returns VBox status code. * @param pVM Pointer to the VM. * @param pSSM Pointer to the SSM handle. */ VMMR3_INT_DECL(int) gimR3KvmSave(PVM pVM, PSSMHANDLE pSSM) { PCGIMKVM pcKvm = &pVM->gim.s.u.Kvm; /* * Save the KVM SSM version. */ SSMR3PutU32(pSSM, GIM_KVM_SAVED_STATE_VERSION); /* * Save per-VCPU data. */ for (uint32_t i = 0; i < pVM->cCpus; i++) { PCGIMKVMCPU pcKvmCpu = &pVM->aCpus[i].gim.s.u.KvmCpu; /* Guest may alter flags (namely GIM_KVM_SYSTEM_TIME_FLAGS_GUEST_PAUSED bit). So re-read them from guest-memory. */ GIMKVMSYSTEMTIME SystemTime; RT_ZERO(SystemTime); if (MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(pcKvmCpu->u64SystemTimeMsr)) { int rc = PGMPhysSimpleReadGCPhys(pVM, &SystemTime, pcKvmCpu->GCPhysSystemTime, sizeof(GIMKVMSYSTEMTIME)); AssertRCReturn(rc, rc); } SSMR3PutU64(pSSM, pcKvmCpu->u64SystemTimeMsr); SSMR3PutU64(pSSM, pcKvmCpu->uTsc); SSMR3PutU64(pSSM, pcKvmCpu->uVirtNanoTS); SSMR3PutGCPhys(pSSM, pcKvmCpu->GCPhysSystemTime); SSMR3PutU32(pSSM, pcKvmCpu->u32SystemTimeVersion); SSMR3PutU8(pSSM, SystemTime.fFlags); } /* * Save per-VM data. */ SSMR3PutU64(pSSM, pcKvm->u64WallClockMsr); return SSMR3PutU32(pSSM, pcKvm->uBaseFeat); }