Mushahid Hussain <[email protected]> writes: > 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/[email protected]/ > > The TLFS marks the bit as reserved. The name comes from Microsoft's > hvdef crate.
This won't be the first time we use side channels to implement Hyper-V features in KVM/QEMU but it's certainly better when feature bits are documented and thus backwards compatible. Cc: linux-hyperv list, maybe there's a chance to get TLFS amended. > > Signed-off-by: Mushahid Hussain <[email protected]> > --- > 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, -- Vitaly
