A nested Hyper-V that sees the frequency MSRs lets L0 own the partition reference time. After a resume from hibernation it issues HvCallRestorePartitionTime with the TSC and the reference counter it saved. Hyper-V offers hibernation to its root partition only when L0 advertises CPUID 0x40000004 EAX bit 20 (RestoreTimeOnResume). Add 'hv-restore-time-on-resume' for the bit. It requires 'hv-frequencies'. KVM reports the bit in KVM_GET_SUPPORTED_HV_CPUID when it handles the hypercall. KVM side: https://lore.kernel.org/kvm/20261005192431.87317-4-hmushi@amazon.co.uk/ The TLFS marks the bit as reserved. The name comes from Microsoft's hvdef crate. Signed-off-by: Mushahid Hussain --- docs/system/i386/hyperv.rst | 9 +++++++++ target/i386/cpu.c | 2 ++ target/i386/cpu.h | 1 + target/i386/kvm/hyperv-proto.h | 1 + target/i386/kvm/kvm.c | 8 ++++++++ 5 files changed, 21 insertions(+) diff --git a/docs/system/i386/hyperv.rst b/docs/system/i386/hyperv.rst index e1babffb0f..2224dc2111 100644 --- a/docs/system/i386/hyperv.rst +++ b/docs/system/i386/hyperv.rst @@ -259,6 +259,15 @@ Existing enlightenments Recommended: ``hv-evmcs`` (Intel) +``hv-restore-time-on-resume`` + The enlightenment is nested specific, it targets Hyper-V on KVM guests. When + enabled, Hyper-V lets L0 (KVM) own the partition reference time and issues + HvCallRestorePartitionTime after a resume from hibernation so that the TSC + and the reference counter continue from the values it saved. Hyper-V offers + hibernation to its root partition only when this enlightenment is present. + + Requires: ``hv-frequencies`` + Supplementary features ---------------------- diff --git a/target/i386/cpu.c b/target/i386/cpu.c index f3bc6911c1..9fa14f6fab 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -10769,6 +10769,8 @@ static const Property x86_cpu_properties[] = { HYPERV_FEAT_TLBFLUSH_EXT, 0), DEFINE_PROP_BIT64("hv-tlbflush-direct", X86CPU, hyperv_features, HYPERV_FEAT_TLBFLUSH_DIRECT, 0), + DEFINE_PROP_BIT64("hv-restore-time-on-resume", X86CPU, hyperv_features, + HYPERV_FEAT_RESTORE_TIME_ON_RESUME, 0), DEFINE_PROP_ON_OFF_AUTO("hv-no-nonarch-coresharing", X86CPU, hyperv_no_nonarch_cs, ON_OFF_AUTO_OFF), #ifdef CONFIG_SYNDBG diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 786957fadd..dab559a3d8 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1487,6 +1487,7 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w); #define HYPERV_FEAT_XMM_INPUT 18 #define HYPERV_FEAT_TLBFLUSH_EXT 19 #define HYPERV_FEAT_TLBFLUSH_DIRECT 20 +#define HYPERV_FEAT_RESTORE_TIME_ON_RESUME 21 #ifndef HYPERV_SPINLOCK_NEVER_NOTIFY #define HYPERV_SPINLOCK_NEVER_NOTIFY 0xFFFFFFFF diff --git a/target/i386/kvm/hyperv-proto.h b/target/i386/kvm/hyperv-proto.h index a9f056f2f3..e420827a68 100644 --- a/target/i386/kvm/hyperv-proto.h +++ b/target/i386/kvm/hyperv-proto.h @@ -81,6 +81,7 @@ #define HV_EX_PROCESSOR_MASKS_RECOMMENDED (1u << 11) #define HV_ENLIGHTENED_VMCS_RECOMMENDED (1u << 14) #define HV_NO_NONARCH_CORESHARING (1u << 18) +#define HV_RESTORE_TIME_ON_RESUME (1u << 20) /* * HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX bits diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index a72b6e6b74..1b16af7cd4 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -1137,6 +1137,14 @@ static struct { }, .dependencies = BIT(HYPERV_FEAT_VAPIC) }, + [HYPERV_FEAT_RESTORE_TIME_ON_RESUME] = { + .desc = "partition time restore (hv-restore-time-on-resume)", + .flags = { + {.func = HV_CPUID_ENLIGHTMENT_INFO, .reg = R_EAX, + .bits = HV_RESTORE_TIME_ON_RESUME} + }, + .dependencies = BIT(HYPERV_FEAT_FREQUENCIES) + }, }; static struct kvm_cpuid2 *try_get_hv_cpuid(CPUState *cs, int max, -- 2.47.3