[1/1] cpu: report hyperv feature words through qom
diff mbox

Message ID 1465900120-2350-1-git-send-email-den@openvz.org
State New
Headers show

Commit Message

Denis V. Lunev June 14, 2016, 10:28 a.m. UTC
From: Evgeny Yakovlev <eyakovlev@virtuozzo.com>

This change adds hyperv feature words report through qom rpc.

When VM is configured with hyperv features enabled libvirt will check that
required featured words are set in cpuid leaf 40000003 through qom
request.

Currently qemu does not report hyperv feature words which prevents windows
guests from starting with libvirt.

Signed-off-by: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Richard Henderson <rth@twiddle.net>
CC: Eduardo Habkost <ehabkost@redhat.com>
CC: Marcelo Tosatti <mtosatti@redhat.com>
---
 target-i386/cpu.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 target-i386/cpu.h |  3 +++
 target-i386/kvm.c |  3 +++
 3 files changed, 53 insertions(+)

Comments

Eduardo Habkost June 14, 2016, 7:59 p.m. UTC | #1
On Tue, Jun 14, 2016 at 01:28:40PM +0300, Denis V. Lunev wrote:
> From: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
> 
> This change adds hyperv feature words report through qom rpc.
> 
> When VM is configured with hyperv features enabled libvirt will check that
> required featured words are set in cpuid leaf 40000003 through qom
> request.
> 
> Currently qemu does not report hyperv feature words which prevents windows
> guests from starting with libvirt.
> 
> Signed-off-by: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> CC: Paolo Bonzini <pbonzini@redhat.com>
> CC: Richard Henderson <rth@twiddle.net>
> CC: Eduardo Habkost <ehabkost@redhat.com>
> CC: Marcelo Tosatti <mtosatti@redhat.com>

Which QEMU version did you use to test this? Some of those properties already
exist. See:

  static Property x86_cpu_properties[] = {
      [...]
      { .name  = "hv-spinlocks", .info  = &qdev_prop_spinlocks },
      DEFINE_PROP_BOOL("hv-relaxed", X86CPU, hyperv_relaxed_timing, false),
      DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false),
      DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false),
      DEFINE_PROP_BOOL("hv-crash", X86CPU, hyperv_crash, false),
      DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
      DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
      DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
      DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
      DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false),
      [...]
      DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
      DEFINE_PROP_END_OF_LIST()
  };

QEMU will crash if you try to register the properties twice:

  $ ./x86_64-softmmu/qemu-system-x86_64
  qemu-system-x86_64: /home/ehabkost/rh/proj/virt/qemu/target-i386/cpu.c:3094: x86_cpu_register_bit_prop: Assertion `fp->ptr == field' failed.
  Aborted (core dumped)

I like the idea of moving hyperv feature information inside the features array,
though.

See additional comments below:

> ---
>  target-i386/cpu.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
>  target-i386/cpu.h |  3 +++
>  target-i386/kvm.c |  3 +++
>  3 files changed, 53 insertions(+)
> 
> diff --git a/target-i386/cpu.c b/target-i386/cpu.c
> index 895a386..ea01f06 100644
> --- a/target-i386/cpu.c
> +++ b/target-i386/cpu.c
> @@ -244,6 +244,41 @@ static const char *kvm_feature_name[] = {
>      NULL, NULL, NULL, NULL,
>  };
>  
> +static const char *hyperv_priv_feature_name[] = {
> +    "hv_runtime", "hv_refcount", "hv_synic", "hv_stimer",
> +    "hv_apic", "hv_hypercall", "hv_vpindex", "hv_reset",
> +    "hv_stats", "hv_reftsc", "hv_idle", "hv_frequency",

I sent a patch some time ago to change all feature names to use "-" instead of
"_". But this can be fixed when applying the patch, if necessary.

> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +};
> +
> +static const char *hyperv_ident_feature_name[] = {
> +    "hv_create_partitions", "hv_access_partition_id",
> +    "hv_access_memory_pool", "hv_adjust_message_buffers",
> +    "hv_post_messages", "hv_signal_events",
> +    "hv_create_port", "hv_connect_port",
> +    "hv_access_stats", NULL, NULL, "hv_debugging",
> +    "hv_cpu_power_management", "hv_configure_profiler", NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +};
> +
> +static const char *hyperv_misc_feature_name[] = {
> +    "hv_mwait", "hv_guest_debugging", "hv_perf_monitor", "hv_cpu_dynamic_part",
> +    "hv_hypercall_params_xmm", "hv_guest_idle_state", NULL, NULL,
> +    NULL, NULL, "hv_guest_crash_msr", NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +};
> +
>  static const char *svm_feature_name[] = {
>      "npt", "lbrv", "svm_lock", "nrip_save",
>      "tsc_scale", "vmcb_clean",  "flushbyasid", "decodeassists",
> @@ -410,6 +445,18 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
>          .cpuid_eax = KVM_CPUID_FEATURES, .cpuid_reg = R_EAX,
>          .tcg_features = TCG_KVM_FEATURES,
>      },
> +    [FEAT_HYPERV_EAX] = {
> +        .feat_names = hyperv_priv_feature_name,
> +        .cpuid_eax = 0x40000003, .cpuid_reg = R_EAX,
> +    },
> +    [FEAT_HYPERV_EBX] = {
> +        .feat_names = hyperv_ident_feature_name,
> +        .cpuid_eax = 0x40000003, .cpuid_reg = R_EBX,
> +    },
> +    [FEAT_HYPERV_EDX] = {
> +        .feat_names = hyperv_misc_feature_name,
> +        .cpuid_eax = 0x40000003, .cpuid_reg = R_EDX,
> +    },
>      [FEAT_SVM] = {
>          .feat_names = svm_feature_name,
>          .cpuid_eax = 0x8000000A, .cpuid_reg = R_EDX,
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index 0426459..d3b7ad4 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -440,6 +440,9 @@ typedef enum FeatureWord {
>      FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */
>      FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
>      FEAT_KVM,           /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
> +    FEAT_HYPERV_EAX,    /* CPUID[4000_0003].EAX */
> +    FEAT_HYPERV_EBX,    /* CPUID[4000_0003].EBX */
> +    FEAT_HYPERV_EDX,    /* CPUID[4000_0003].EDX */
>      FEAT_SVM,           /* CPUID[8000_000A].EDX */
>      FEAT_XSAVE,         /* CPUID[EAX=0xd,ECX=1].EAX */
>      FEAT_6_EAX,         /* CPUID[6].EAX */
> diff --git a/target-i386/kvm.c b/target-i386/kvm.c
> index abf50e6..f4ca8c4 100644
> --- a/target-i386/kvm.c
> +++ b/target-i386/kvm.c
> @@ -679,6 +679,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
>              }
>              c->eax |= HV_X64_MSR_SYNTIMER_AVAILABLE;
>          }
> +        env->features[FEAT_HYPERV_EAX] = c->eax;
> +        env->features[FEAT_HYPERV_EBX] = c->ebx;
> +        env->features[FEAT_HYPERV_EDX] = c->edx;

We normally store the configured features inside env->features
(using the properties), and then CPUID data is filled using
env->features. Not the other way around.

In other words, the new env->features[FEAT_HYPERV_*] bits can simply replace
the existing X86CPU::hyperv_* booleans.
Denis V. Lunev June 14, 2016, 8:45 p.m. UTC | #2
On 06/14/2016 10:59 PM, Eduardo Habkost wrote:
> On Tue, Jun 14, 2016 at 01:28:40PM +0300, Denis V. Lunev wrote:
>> From: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
>>
>> This change adds hyperv feature words report through qom rpc.
>>
>> When VM is configured with hyperv features enabled libvirt will check that
>> required featured words are set in cpuid leaf 40000003 through qom
>> request.
>>
>> Currently qemu does not report hyperv feature words which prevents windows
>> guests from starting with libvirt.
>>
>> Signed-off-by: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
>> Signed-off-by: Denis V. Lunev <den@openvz.org>
>> CC: Paolo Bonzini <pbonzini@redhat.com>
>> CC: Richard Henderson <rth@twiddle.net>
>> CC: Eduardo Habkost <ehabkost@redhat.com>
>> CC: Marcelo Tosatti <mtosatti@redhat.com>
> Which QEMU version did you use to test this? Some of those properties already
> exist. See:
>
>    static Property x86_cpu_properties[] = {
>        [...]
>        { .name  = "hv-spinlocks", .info  = &qdev_prop_spinlocks },
>        DEFINE_PROP_BOOL("hv-relaxed", X86CPU, hyperv_relaxed_timing, false),
>        DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false),
>        DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false),
>        DEFINE_PROP_BOOL("hv-crash", X86CPU, hyperv_crash, false),
>        DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
>        DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
>        DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
>        DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
>        DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false),
>        [...]
>        DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
>        DEFINE_PROP_END_OF_LIST()
>    };
>
> QEMU will crash if you try to register the properties twice:
>
>    $ ./x86_64-softmmu/qemu-system-x86_64
>    qemu-system-x86_64: /home/ehabkost/rh/proj/virt/qemu/target-i386/cpu.c:3094: x86_cpu_register_bit_prop: Assertion `fp->ptr == field' failed.
>    Aborted (core dumped)
>
> I like the idea of moving hyperv feature information inside the features array,
> though.
no, idea is a bit different.

The user selects properties in the command line to enable
different HyperV enlightenments. This is how we do that
and this is how the QEMU is expected to work.

After that libvirt starts to check that these properties do
work. In order to do that it executes qom-get and expects
to find enabled HyperV enlightenments in the guest CPUID.

This is the idea of this patch.
Eduardo Habkost June 14, 2016, 8:54 p.m. UTC | #3
On Tue, Jun 14, 2016 at 11:45:08PM +0300, Denis V. Lunev wrote:
> On 06/14/2016 10:59 PM, Eduardo Habkost wrote:
> > On Tue, Jun 14, 2016 at 01:28:40PM +0300, Denis V. Lunev wrote:
> > > From: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
> > > 
> > > This change adds hyperv feature words report through qom rpc.
> > > 
> > > When VM is configured with hyperv features enabled libvirt will check that
> > > required featured words are set in cpuid leaf 40000003 through qom
> > > request.
> > > 
> > > Currently qemu does not report hyperv feature words which prevents windows
> > > guests from starting with libvirt.
> > > 
> > > Signed-off-by: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
> > > Signed-off-by: Denis V. Lunev <den@openvz.org>
> > > CC: Paolo Bonzini <pbonzini@redhat.com>
> > > CC: Richard Henderson <rth@twiddle.net>
> > > CC: Eduardo Habkost <ehabkost@redhat.com>
> > > CC: Marcelo Tosatti <mtosatti@redhat.com>
> > Which QEMU version did you use to test this? Some of those properties already
> > exist. See:
> > 
> >    static Property x86_cpu_properties[] = {
> >        [...]
> >        { .name  = "hv-spinlocks", .info  = &qdev_prop_spinlocks },
> >        DEFINE_PROP_BOOL("hv-relaxed", X86CPU, hyperv_relaxed_timing, false),
> >        DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false),
> >        DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false),
> >        DEFINE_PROP_BOOL("hv-crash", X86CPU, hyperv_crash, false),
> >        DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
> >        DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
> >        DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
> >        DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
> >        DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false),
> >        [...]
> >        DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
> >        DEFINE_PROP_END_OF_LIST()
> >    };
> > 
> > QEMU will crash if you try to register the properties twice:
> > 
> >    $ ./x86_64-softmmu/qemu-system-x86_64
> >    qemu-system-x86_64: /home/ehabkost/rh/proj/virt/qemu/target-i386/cpu.c:3094: x86_cpu_register_bit_prop: Assertion `fp->ptr == field' failed.
> >    Aborted (core dumped)
> > 
> > I like the idea of moving hyperv feature information inside the features array,
> > though.
> no, idea is a bit different.
> 
> The user selects properties in the command line to enable
> different HyperV enlightenments. This is how we do that
> and this is how the QEMU is expected to work.
> 
> After that libvirt starts to check that these properties do
> work. In order to do that it executes qom-get and expects
> to find enabled HyperV enlightenments in the guest CPUID.
> 
> This is the idea of this patch.

And why exactly moving hyperv feature information inside the
CPUX86State::features array wouldn't do exactly what you say
above?
Denis V. Lunev June 14, 2016, 8:59 p.m. UTC | #4
On 06/14/2016 11:54 PM, Eduardo Habkost wrote:
> On Tue, Jun 14, 2016 at 11:45:08PM +0300, Denis V. Lunev wrote:
>> On 06/14/2016 10:59 PM, Eduardo Habkost wrote:
>>> On Tue, Jun 14, 2016 at 01:28:40PM +0300, Denis V. Lunev wrote:
>>>> From: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
>>>>
>>>> This change adds hyperv feature words report through qom rpc.
>>>>
>>>> When VM is configured with hyperv features enabled libvirt will check that
>>>> required featured words are set in cpuid leaf 40000003 through qom
>>>> request.
>>>>
>>>> Currently qemu does not report hyperv feature words which prevents windows
>>>> guests from starting with libvirt.
>>>>
>>>> Signed-off-by: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
>>>> Signed-off-by: Denis V. Lunev <den@openvz.org>
>>>> CC: Paolo Bonzini <pbonzini@redhat.com>
>>>> CC: Richard Henderson <rth@twiddle.net>
>>>> CC: Eduardo Habkost <ehabkost@redhat.com>
>>>> CC: Marcelo Tosatti <mtosatti@redhat.com>
>>> Which QEMU version did you use to test this? Some of those properties already
>>> exist. See:
>>>
>>>     static Property x86_cpu_properties[] = {
>>>         [...]
>>>         { .name  = "hv-spinlocks", .info  = &qdev_prop_spinlocks },
>>>         DEFINE_PROP_BOOL("hv-relaxed", X86CPU, hyperv_relaxed_timing, false),
>>>         DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false),
>>>         DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false),
>>>         DEFINE_PROP_BOOL("hv-crash", X86CPU, hyperv_crash, false),
>>>         DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
>>>         DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
>>>         DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
>>>         DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
>>>         DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false),
>>>         [...]
>>>         DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
>>>         DEFINE_PROP_END_OF_LIST()
>>>     };
>>>
>>> QEMU will crash if you try to register the properties twice:
>>>
>>>     $ ./x86_64-softmmu/qemu-system-x86_64
>>>     qemu-system-x86_64: /home/ehabkost/rh/proj/virt/qemu/target-i386/cpu.c:3094: x86_cpu_register_bit_prop: Assertion `fp->ptr == field' failed.
>>>     Aborted (core dumped)
>>>
>>> I like the idea of moving hyperv feature information inside the features array,
>>> though.
>> no, idea is a bit different.
>>
>> The user selects properties in the command line to enable
>> different HyperV enlightenments. This is how we do that
>> and this is how the QEMU is expected to work.
>>
>> After that libvirt starts to check that these properties do
>> work. In order to do that it executes qom-get and expects
>> to find enabled HyperV enlightenments in the guest CPUID.
>>
>> This is the idea of this patch.
> And why exactly moving hyperv feature information inside the
> CPUX86State::features array wouldn't do exactly what you say
> above?
>
property remains ;)

OK, may be I have missed you point. I fear word "move"
in your letter. I think we "add" it to features.

Anyway, I got your point that features comes first,
CPUID is filled in the base of features. No prob.

Den
Eduardo Habkost June 14, 2016, 9:16 p.m. UTC | #5
On Tue, Jun 14, 2016 at 11:59:18PM +0300, Denis V. Lunev wrote:
> On 06/14/2016 11:54 PM, Eduardo Habkost wrote:
> > On Tue, Jun 14, 2016 at 11:45:08PM +0300, Denis V. Lunev wrote:
> > > On 06/14/2016 10:59 PM, Eduardo Habkost wrote:
> > > > On Tue, Jun 14, 2016 at 01:28:40PM +0300, Denis V. Lunev wrote:
> > > > > From: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
> > > > > 
> > > > > This change adds hyperv feature words report through qom rpc.
> > > > > 
> > > > > When VM is configured with hyperv features enabled libvirt will check that
> > > > > required featured words are set in cpuid leaf 40000003 through qom
> > > > > request.
> > > > > 
> > > > > Currently qemu does not report hyperv feature words which prevents windows
> > > > > guests from starting with libvirt.
> > > > > 
> > > > > Signed-off-by: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
> > > > > Signed-off-by: Denis V. Lunev <den@openvz.org>
> > > > > CC: Paolo Bonzini <pbonzini@redhat.com>
> > > > > CC: Richard Henderson <rth@twiddle.net>
> > > > > CC: Eduardo Habkost <ehabkost@redhat.com>
> > > > > CC: Marcelo Tosatti <mtosatti@redhat.com>
> > > > Which QEMU version did you use to test this? Some of those properties already
> > > > exist. See:
> > > > 
> > > >     static Property x86_cpu_properties[] = {
> > > >         [...]
> > > >         { .name  = "hv-spinlocks", .info  = &qdev_prop_spinlocks },
> > > >         DEFINE_PROP_BOOL("hv-relaxed", X86CPU, hyperv_relaxed_timing, false),
> > > >         DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false),
> > > >         DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false),
> > > >         DEFINE_PROP_BOOL("hv-crash", X86CPU, hyperv_crash, false),
> > > >         DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
> > > >         DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
> > > >         DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
> > > >         DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
> > > >         DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false),
> > > >         [...]
> > > >         DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
> > > >         DEFINE_PROP_END_OF_LIST()
> > > >     };
> > > > 
> > > > QEMU will crash if you try to register the properties twice:
> > > > 
> > > >     $ ./x86_64-softmmu/qemu-system-x86_64
> > > >     qemu-system-x86_64: /home/ehabkost/rh/proj/virt/qemu/target-i386/cpu.c:3094: x86_cpu_register_bit_prop: Assertion `fp->ptr == field' failed.
> > > >     Aborted (core dumped)
> > > > 
> > > > I like the idea of moving hyperv feature information inside the features array,
> > > > though.
> > > no, idea is a bit different.
> > > 
> > > The user selects properties in the command line to enable
> > > different HyperV enlightenments. This is how we do that
> > > and this is how the QEMU is expected to work.
> > > 
> > > After that libvirt starts to check that these properties do
> > > work. In order to do that it executes qom-get and expects
> > > to find enabled HyperV enlightenments in the guest CPUID.
> > > 
> > > This is the idea of this patch.
> > And why exactly moving hyperv feature information inside the
> > CPUX86State::features array wouldn't do exactly what you say
> > above?
> > 
> property remains ;)
> 
> OK, may be I have missed you point. I fear word "move"
> in your letter. I think we "add" it to features.

I mean we move data to a different struct field (from the
hyperv_* booleans to the features array), and let the existing
feature property system handle it.

Your patch does that partially, but it conflicts with the
existing properties registered at x86_cpu_properties.

But we also need to make kvm_arch_get_supported_cpuid() handle
the hyperv CPUID leaves (to replace the existing
kvm_check_extensions() and has_msr_* checks in
kvm_arch_init_vcpu()).

After we do that, some things should work automatically:
* New hv-* properties available in QOM and "-cpu";
* hyperv support for the "check" and "enforce" options;
* hyperv support in "-cpu host'; and
* hyperv information returned in the "feature-words" and
  "filtered-features" QOM properties.

See how FEAT_KVM is handled in target-i386/cpu.c and
kvm_arch_init_vcpu(), for reference.

Patch
diff mbox

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 895a386..ea01f06 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -244,6 +244,41 @@  static const char *kvm_feature_name[] = {
     NULL, NULL, NULL, NULL,
 };
 
+static const char *hyperv_priv_feature_name[] = {
+    "hv_runtime", "hv_refcount", "hv_synic", "hv_stimer",
+    "hv_apic", "hv_hypercall", "hv_vpindex", "hv_reset",
+    "hv_stats", "hv_reftsc", "hv_idle", "hv_frequency",
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+};
+
+static const char *hyperv_ident_feature_name[] = {
+    "hv_create_partitions", "hv_access_partition_id",
+    "hv_access_memory_pool", "hv_adjust_message_buffers",
+    "hv_post_messages", "hv_signal_events",
+    "hv_create_port", "hv_connect_port",
+    "hv_access_stats", NULL, NULL, "hv_debugging",
+    "hv_cpu_power_management", "hv_configure_profiler", NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+};
+
+static const char *hyperv_misc_feature_name[] = {
+    "hv_mwait", "hv_guest_debugging", "hv_perf_monitor", "hv_cpu_dynamic_part",
+    "hv_hypercall_params_xmm", "hv_guest_idle_state", NULL, NULL,
+    NULL, NULL, "hv_guest_crash_msr", NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+};
+
 static const char *svm_feature_name[] = {
     "npt", "lbrv", "svm_lock", "nrip_save",
     "tsc_scale", "vmcb_clean",  "flushbyasid", "decodeassists",
@@ -410,6 +445,18 @@  static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
         .cpuid_eax = KVM_CPUID_FEATURES, .cpuid_reg = R_EAX,
         .tcg_features = TCG_KVM_FEATURES,
     },
+    [FEAT_HYPERV_EAX] = {
+        .feat_names = hyperv_priv_feature_name,
+        .cpuid_eax = 0x40000003, .cpuid_reg = R_EAX,
+    },
+    [FEAT_HYPERV_EBX] = {
+        .feat_names = hyperv_ident_feature_name,
+        .cpuid_eax = 0x40000003, .cpuid_reg = R_EBX,
+    },
+    [FEAT_HYPERV_EDX] = {
+        .feat_names = hyperv_misc_feature_name,
+        .cpuid_eax = 0x40000003, .cpuid_reg = R_EDX,
+    },
     [FEAT_SVM] = {
         .feat_names = svm_feature_name,
         .cpuid_eax = 0x8000000A, .cpuid_reg = R_EDX,
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 0426459..d3b7ad4 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -440,6 +440,9 @@  typedef enum FeatureWord {
     FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */
     FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
     FEAT_KVM,           /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
+    FEAT_HYPERV_EAX,    /* CPUID[4000_0003].EAX */
+    FEAT_HYPERV_EBX,    /* CPUID[4000_0003].EBX */
+    FEAT_HYPERV_EDX,    /* CPUID[4000_0003].EDX */
     FEAT_SVM,           /* CPUID[8000_000A].EDX */
     FEAT_XSAVE,         /* CPUID[EAX=0xd,ECX=1].EAX */
     FEAT_6_EAX,         /* CPUID[6].EAX */
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index abf50e6..f4ca8c4 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -679,6 +679,9 @@  int kvm_arch_init_vcpu(CPUState *cs)
             }
             c->eax |= HV_X64_MSR_SYNTIMER_AVAILABLE;
         }
+        env->features[FEAT_HYPERV_EAX] = c->eax;
+        env->features[FEAT_HYPERV_EBX] = c->ebx;
+        env->features[FEAT_HYPERV_EDX] = c->edx;
         c = &cpuid_data.entries[cpuid_i++];
         c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
         if (cpu->hyperv_relaxed_timing) {