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


Reply via email to