diff mbox series

[PULL,07/17] i386: move hyperv_vendor_id initialization to x86_cpu_realizefn()

Message ID 20201217184620.3945917-8-ehabkost@redhat.com
State New
Headers show
Series [PULL,01/17] i386: move kvm accel files into kvm/ | expand

Commit Message

Eduardo Habkost Dec. 17, 2020, 6:46 p.m. UTC
From: Vitaly Kuznetsov <vkuznets@redhat.com>

As a preparation to expanding Hyper-V CPU features early, move
hyperv_vendor_id initialization to x86_cpu_realizefn(). Introduce
x86_cpu_hyperv_realize() to not not pollute x86_cpu_realizefn()
itself.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20201119103221.1665171-2-vkuznets@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 target/i386/cpu.h     |  3 ++-
 target/i386/cpu.c     | 23 ++++++++++++++++++++++-
 target/i386/kvm/kvm.c | 25 ++++++++++---------------
 3 files changed, 34 insertions(+), 17 deletions(-)

Comments

Claudio Fontana Dec. 17, 2020, 10:33 p.m. UTC | #1
Hello all,

On 12/17/20 7:46 PM, Eduardo Habkost wrote:
> From: Vitaly Kuznetsov <vkuznets@redhat.com>
> 
> As a preparation to expanding Hyper-V CPU features early, move
> hyperv_vendor_id initialization to x86_cpu_realizefn(). Introduce
> x86_cpu_hyperv_realize() to not not pollute x86_cpu_realizefn()
> itself.

this seems to fit very well the ongoing work on separating accelerator specific realize functions;

related to the previous discussions about the class hierarchies,
do you think that we should have a separate class in target/i386/kvm/ for a hyperv variant of the kvm-cpu.c?

Should it be a separate class or a subclass of "kvm-accel-x86_64-cpu" ?

Thanks,

Claudio


> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
> Message-Id: <20201119103221.1665171-2-vkuznets@redhat.com>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
>  target/i386/cpu.h     |  3 ++-
>  target/i386/cpu.c     | 23 ++++++++++++++++++++++-
>  target/i386/kvm/kvm.c | 25 ++++++++++---------------
>  3 files changed, 34 insertions(+), 17 deletions(-)
> 
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 343e51baab..ad9ef559fc 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -1659,11 +1659,12 @@ struct X86CPU {
>      uint64_t ucode_rev;
>  
>      uint32_t hyperv_spinlock_attempts;
> -    char *hyperv_vendor_id;
> +    char *hyperv_vendor;
>      bool hyperv_synic_kvm_only;
>      uint64_t hyperv_features;
>      bool hyperv_passthrough;
>      OnOffAuto hyperv_no_nonarch_cs;
> +    uint32_t hyperv_vendor_id[3];
>  
>      bool check_cpuid;
>      bool enforce_cpuid;
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 77f0e44df8..599526406a 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -6544,6 +6544,25 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool verbose)
>      }
>  }
>  
> +static void x86_cpu_hyperv_realize(X86CPU *cpu)
> +{
> +    size_t len;
> +
> +    /* Hyper-V vendor id */
> +    if (!cpu->hyperv_vendor) {
> +        memcpy(cpu->hyperv_vendor_id, "Microsoft Hv", 12);
> +    } else {
> +        len = strlen(cpu->hyperv_vendor);
> +
> +        if (len > 12) {
> +            warn_report("hv-vendor-id truncated to 12 characters");
> +            len = 12;
> +        }
> +        memset(cpu->hyperv_vendor_id, 0, 12);
> +        memcpy(cpu->hyperv_vendor_id, cpu->hyperv_vendor, len);
> +    }
> +}
> +
>  static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
>  {
>      CPUState *cs = CPU(dev);
> @@ -6715,6 +6734,8 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
>          env->cache_info_amd.l3_cache = &legacy_l3_cache;
>      }
>  
> +    /* Process Hyper-V enlightenments */
> +    x86_cpu_hyperv_realize(cpu);
>  
>      cpu_exec_realizefn(cs, &local_err);
>      if (local_err != NULL) {
> @@ -7218,7 +7239,7 @@ static Property x86_cpu_properties[] = {
>      DEFINE_PROP_UINT32("min-xlevel2", X86CPU, env.cpuid_min_xlevel2, 0),
>      DEFINE_PROP_UINT64("ucode-rev", X86CPU, ucode_rev, 0),
>      DEFINE_PROP_BOOL("full-cpuid-auto-level", X86CPU, full_cpuid_auto_level, true),
> -    DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
> +    DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor),
>      DEFINE_PROP_BOOL("cpuid-0xb", X86CPU, enable_cpuid_0xb, true),
>      DEFINE_PROP_BOOL("lmce", X86CPU, enable_lmce, false),
>      DEFINE_PROP_BOOL("l3-cache", X86CPU, enable_l3_cache, true),
> diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
> index bcfa4b03e0..6a5d91e39f 100644
> --- a/target/i386/kvm/kvm.c
> +++ b/target/i386/kvm/kvm.c
> @@ -1208,6 +1208,13 @@ static int hyperv_handle_properties(CPUState *cs,
>          memcpy(cpuid_ent, &cpuid->entries[0],
>                 cpuid->nent * sizeof(cpuid->entries[0]));
>  
> +        c = cpuid_find_entry(cpuid, HV_CPUID_VENDOR_AND_MAX_FUNCTIONS, 0);
> +        if (c) {
> +            cpu->hyperv_vendor_id[0] = c->ebx;
> +            cpu->hyperv_vendor_id[1] = c->ecx;
> +            cpu->hyperv_vendor_id[2] = c->edx;
> +        }
> +
>          c = cpuid_find_entry(cpuid, HV_CPUID_FEATURES, 0);
>          if (c) {
>              env->features[FEAT_HYPERV_EAX] = c->eax;
> @@ -1282,23 +1289,11 @@ static int hyperv_handle_properties(CPUState *cs,
>  
>      c = &cpuid_ent[cpuid_i++];
>      c->function = HV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
> -    if (!cpu->hyperv_vendor_id) {
> -        memcpy(signature, "Microsoft Hv", 12);
> -    } else {
> -        size_t len = strlen(cpu->hyperv_vendor_id);
> -
> -        if (len > 12) {
> -            error_report("hv-vendor-id truncated to 12 characters");
> -            len = 12;
> -        }
> -        memset(signature, 0, 12);
> -        memcpy(signature, cpu->hyperv_vendor_id, len);
> -    }
>      c->eax = hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS) ?
>          HV_CPUID_NESTED_FEATURES : HV_CPUID_IMPLEMENT_LIMITS;
> -    c->ebx = signature[0];
> -    c->ecx = signature[1];
> -    c->edx = signature[2];
> +    c->ebx = cpu->hyperv_vendor_id[0];
> +    c->ecx = cpu->hyperv_vendor_id[1];
> +    c->edx = cpu->hyperv_vendor_id[2];
>  
>      c = &cpuid_ent[cpuid_i++];
>      c->function = HV_CPUID_INTERFACE;
>
Eduardo Habkost Dec. 17, 2020, 10:53 p.m. UTC | #2
On Thu, Dec 17, 2020 at 11:33:57PM +0100, Claudio Fontana wrote:
> Hello all,
> 
> On 12/17/20 7:46 PM, Eduardo Habkost wrote:
> > From: Vitaly Kuznetsov <vkuznets@redhat.com>
> > 
> > As a preparation to expanding Hyper-V CPU features early, move
> > hyperv_vendor_id initialization to x86_cpu_realizefn(). Introduce
> > x86_cpu_hyperv_realize() to not not pollute x86_cpu_realizefn()
> > itself.
> 
> this seems to fit very well the ongoing work on separating accelerator specific realize functions;
> 
> related to the previous discussions about the class hierarchies,
> do you think that we should have a separate class in target/i386/kvm/ for a hyperv variant of the kvm-cpu.c?
> 
> Should it be a separate class or a subclass of "kvm-accel-x86_64-cpu" ?

I don't see how a separate QOM class for Hyper-V would be helpful
here.  What would be the problem you are trying to solve in this
case?

Note that the Hyper-V features here are just a set of
configurable VCPU features that appear on CPUID.  This is not a
different kind of hypervisor and/or a different kind of
accelerator.
Claudio Fontana Dec. 17, 2020, 11:34 p.m. UTC | #3
On 12/17/20 11:53 PM, Eduardo Habkost wrote:
> On Thu, Dec 17, 2020 at 11:33:57PM +0100, Claudio Fontana wrote:
>> Hello all,
>>
>> On 12/17/20 7:46 PM, Eduardo Habkost wrote:
>>> From: Vitaly Kuznetsov <vkuznets@redhat.com>
>>>
>>> As a preparation to expanding Hyper-V CPU features early, move
>>> hyperv_vendor_id initialization to x86_cpu_realizefn(). Introduce
>>> x86_cpu_hyperv_realize() to not not pollute x86_cpu_realizefn()
>>> itself.
>>
>> this seems to fit very well the ongoing work on separating accelerator specific realize functions;
>>
>> related to the previous discussions about the class hierarchies,
>> do you think that we should have a separate class in target/i386/kvm/ for a hyperv variant of the kvm-cpu.c?
>>
>> Should it be a separate class or a subclass of "kvm-accel-x86_64-cpu" ?
> 
> I don't see how a separate QOM class for Hyper-V would be helpful
> here.  What would be the problem you are trying to solve in this
> case?

there is now a call to accelerator specific code x86_hyperv_cpu_realize just before cpu_exec_realize,
tying the generic target/i386/cpu.c code to kvm/hyperv-specific accel initialization.

if this is just a feature of the kvm accel, maybe I should just move all to kvm-cpu.c and that's it.

Thanks,

Claudio

> 
> Note that the Hyper-V features here are just a set of
> configurable VCPU features that appear on CPUID.  This is not a
> different kind of hypervisor and/or a different kind of
> accelerator.
>
Eduardo Habkost Dec. 17, 2020, 11:47 p.m. UTC | #4
On Fri, Dec 18, 2020 at 12:34:46AM +0100, Claudio Fontana wrote:
> On 12/17/20 11:53 PM, Eduardo Habkost wrote:
> > On Thu, Dec 17, 2020 at 11:33:57PM +0100, Claudio Fontana wrote:
> >> Hello all,
> >>
> >> On 12/17/20 7:46 PM, Eduardo Habkost wrote:
> >>> From: Vitaly Kuznetsov <vkuznets@redhat.com>
> >>>
> >>> As a preparation to expanding Hyper-V CPU features early, move
> >>> hyperv_vendor_id initialization to x86_cpu_realizefn(). Introduce
> >>> x86_cpu_hyperv_realize() to not not pollute x86_cpu_realizefn()
> >>> itself.
> >>
> >> this seems to fit very well the ongoing work on separating accelerator specific realize functions;
> >>
> >> related to the previous discussions about the class hierarchies,
> >> do you think that we should have a separate class in target/i386/kvm/ for a hyperv variant of the kvm-cpu.c?
> >>
> >> Should it be a separate class or a subclass of "kvm-accel-x86_64-cpu" ?
> > 
> > I don't see how a separate QOM class for Hyper-V would be helpful
> > here.  What would be the problem you are trying to solve in this
> > case?
> 
> there is now a call to accelerator specific code x86_hyperv_cpu_realize just before cpu_exec_realize,
> tying the generic target/i386/cpu.c code to kvm/hyperv-specific accel initialization.
> 
> if this is just a feature of the kvm accel, maybe I should just move all to kvm-cpu.c and that's it.

That would make sense.  If we decide this is a KVM-specific
feature, this code can be moved to kvm_cpu_realizefn(), provided
by the kvm-accel-x86_64-cpu class added by your series.

However, I'm not sure we can say this is a KVM-specific feature.
The feature is currently only supported by the KVM accelerator,
but I'd say it is a generic feature.
Claudio Fontana Dec. 18, 2020, 12:07 a.m. UTC | #5
On 12/18/20 12:47 AM, Eduardo Habkost wrote:
> On Fri, Dec 18, 2020 at 12:34:46AM +0100, Claudio Fontana wrote:
>> On 12/17/20 11:53 PM, Eduardo Habkost wrote:
>>> On Thu, Dec 17, 2020 at 11:33:57PM +0100, Claudio Fontana wrote:
>>>> Hello all,
>>>>
>>>> On 12/17/20 7:46 PM, Eduardo Habkost wrote:
>>>>> From: Vitaly Kuznetsov <vkuznets@redhat.com>
>>>>>
>>>>> As a preparation to expanding Hyper-V CPU features early, move
>>>>> hyperv_vendor_id initialization to x86_cpu_realizefn(). Introduce
>>>>> x86_cpu_hyperv_realize() to not not pollute x86_cpu_realizefn()
>>>>> itself.
>>>>
>>>> this seems to fit very well the ongoing work on separating accelerator specific realize functions;
>>>>
>>>> related to the previous discussions about the class hierarchies,
>>>> do you think that we should have a separate class in target/i386/kvm/ for a hyperv variant of the kvm-cpu.c?
>>>>
>>>> Should it be a separate class or a subclass of "kvm-accel-x86_64-cpu" ?
>>>
>>> I don't see how a separate QOM class for Hyper-V would be helpful
>>> here.  What would be the problem you are trying to solve in this
>>> case?
>>
>> there is now a call to accelerator specific code x86_hyperv_cpu_realize just before cpu_exec_realize,
>> tying the generic target/i386/cpu.c code to kvm/hyperv-specific accel initialization.
>>
>> if this is just a feature of the kvm accel, maybe I should just move all to kvm-cpu.c and that's it.
> 
> That would make sense.  If we decide this is a KVM-specific
> feature, this code can be moved to kvm_cpu_realizefn(), provided
> by the kvm-accel-x86_64-cpu class added by your series.
> 
> However, I'm not sure we can say this is a KVM-specific feature.
> The feature is currently only supported by the KVM accelerator,
> but I'd say it is a generic feature.
> 

Maybe in the future it will be a generic feature, and we can export it the right way?
It will be super-easy if the feature is well contained.

Until it really is generic though, should it really appear in the middle of x86_cpu_realizefn?
currently the generic code in target/i386/cpu.c contains an unconditional call to:

x86_cpu_hyperv_realize(cpu);

before the call to cpu_exec_realizefn().

the function is defined in this very same file before as:

static void x86_cpu_hyperv_realize(X86CPU *cpu)
{
 ...
}

with a bunch of initializations of hyperv specific data, for example cpu->hyperv_interface_id, cpu->hyperv_vendor_id, cpu->hyperv_version_id.

That data is ever only used in kvm/kvm.c, which is built conditionally under CONFIG_KVM.

So the existing situation is fairly inconsistent in my view, at least for how things are now, and in principle the extra code of the initializations for hyperv should never be executed if !CONFIG_KVM.

Thanks,

Ciao,

Claudio
Eduardo Habkost Dec. 18, 2020, 1:05 a.m. UTC | #6
On Fri, Dec 18, 2020 at 01:07:33AM +0100, Claudio Fontana wrote:
> On 12/18/20 12:47 AM, Eduardo Habkost wrote:
> > On Fri, Dec 18, 2020 at 12:34:46AM +0100, Claudio Fontana wrote:
> >> On 12/17/20 11:53 PM, Eduardo Habkost wrote:
> >>> On Thu, Dec 17, 2020 at 11:33:57PM +0100, Claudio Fontana wrote:
> >>>> Hello all,
> >>>>
> >>>> On 12/17/20 7:46 PM, Eduardo Habkost wrote:
> >>>>> From: Vitaly Kuznetsov <vkuznets@redhat.com>
> >>>>>
> >>>>> As a preparation to expanding Hyper-V CPU features early, move
> >>>>> hyperv_vendor_id initialization to x86_cpu_realizefn(). Introduce
> >>>>> x86_cpu_hyperv_realize() to not not pollute x86_cpu_realizefn()
> >>>>> itself.
> >>>>
> >>>> this seems to fit very well the ongoing work on separating accelerator specific realize functions;
> >>>>
> >>>> related to the previous discussions about the class hierarchies,
> >>>> do you think that we should have a separate class in target/i386/kvm/ for a hyperv variant of the kvm-cpu.c?
> >>>>
> >>>> Should it be a separate class or a subclass of "kvm-accel-x86_64-cpu" ?
> >>>
> >>> I don't see how a separate QOM class for Hyper-V would be helpful
> >>> here.  What would be the problem you are trying to solve in this
> >>> case?
> >>
> >> there is now a call to accelerator specific code x86_hyperv_cpu_realize just before cpu_exec_realize,
> >> tying the generic target/i386/cpu.c code to kvm/hyperv-specific accel initialization.
> >>
> >> if this is just a feature of the kvm accel, maybe I should just move all to kvm-cpu.c and that's it.
> > 
> > That would make sense.  If we decide this is a KVM-specific
> > feature, this code can be moved to kvm_cpu_realizefn(), provided
> > by the kvm-accel-x86_64-cpu class added by your series.
> > 
> > However, I'm not sure we can say this is a KVM-specific feature.
> > The feature is currently only supported by the KVM accelerator,
> > but I'd say it is a generic feature.
> > 
> 
> Maybe in the future it will be a generic feature, and we can export it the right way?
> It will be super-easy if the feature is well contained.
> 
> Until it really is generic though, should it really appear in the middle of x86_cpu_realizefn?
> currently the generic code in target/i386/cpu.c contains an unconditional call to:
> 
> x86_cpu_hyperv_realize(cpu);
> 
> before the call to cpu_exec_realizefn().
> 
> the function is defined in this very same file before as:
> 
> static void x86_cpu_hyperv_realize(X86CPU *cpu)
> {
>  ...
> }
> 
> with a bunch of initializations of hyperv specific data, for example cpu->hyperv_interface_id, cpu->hyperv_vendor_id, cpu->hyperv_version_id.
> 
> That data is ever only used in kvm/kvm.c, which is built conditionally under CONFIG_KVM.
> 
> So the existing situation is fairly inconsistent in my view, at least for how things are now, and in principle the extra code of the initializations for hyperv should never be executed if !CONFIG_KVM.

What's the problem you are trying to solve?  Speed?  Binary size?
Something else?

Moving the code in x86_cpu_hyperv_realize() to kvm-cpu.c sounds
like a drop in the bucket.  It wouldn't get rid of
hyperv-specific code in cpu.c, which includes:
- the "hv-*" properties in x86_cpu_properties[];
- FEAT_HYPERV_* CPUID leaf definitions;
- hyperv code in x86_cpu_get_crash_info().

I wouldn't object if somebody really wants to move it, but I
don't see it as a problem.
Claudio Fontana Dec. 18, 2020, 8:50 a.m. UTC | #7
On 12/18/20 2:05 AM, Eduardo Habkost wrote:
> On Fri, Dec 18, 2020 at 01:07:33AM +0100, Claudio Fontana wrote:
>> On 12/18/20 12:47 AM, Eduardo Habkost wrote:
>>> On Fri, Dec 18, 2020 at 12:34:46AM +0100, Claudio Fontana wrote:
>>>> On 12/17/20 11:53 PM, Eduardo Habkost wrote:
>>>>> On Thu, Dec 17, 2020 at 11:33:57PM +0100, Claudio Fontana wrote:
>>>>>> Hello all,
>>>>>>
>>>>>> On 12/17/20 7:46 PM, Eduardo Habkost wrote:
>>>>>>> From: Vitaly Kuznetsov <vkuznets@redhat.com>
>>>>>>>
>>>>>>> As a preparation to expanding Hyper-V CPU features early, move
>>>>>>> hyperv_vendor_id initialization to x86_cpu_realizefn(). Introduce
>>>>>>> x86_cpu_hyperv_realize() to not not pollute x86_cpu_realizefn()
>>>>>>> itself.
>>>>>>
>>>>>> this seems to fit very well the ongoing work on separating accelerator specific realize functions;
>>>>>>
>>>>>> related to the previous discussions about the class hierarchies,
>>>>>> do you think that we should have a separate class in target/i386/kvm/ for a hyperv variant of the kvm-cpu.c?
>>>>>>
>>>>>> Should it be a separate class or a subclass of "kvm-accel-x86_64-cpu" ?
>>>>>
>>>>> I don't see how a separate QOM class for Hyper-V would be helpful
>>>>> here.  What would be the problem you are trying to solve in this
>>>>> case?
>>>>
>>>> there is now a call to accelerator specific code x86_hyperv_cpu_realize just before cpu_exec_realize,
>>>> tying the generic target/i386/cpu.c code to kvm/hyperv-specific accel initialization.
>>>>
>>>> if this is just a feature of the kvm accel, maybe I should just move all to kvm-cpu.c and that's it.
>>>
>>> That would make sense.  If we decide this is a KVM-specific
>>> feature, this code can be moved to kvm_cpu_realizefn(), provided
>>> by the kvm-accel-x86_64-cpu class added by your series.
>>>
>>> However, I'm not sure we can say this is a KVM-specific feature.
>>> The feature is currently only supported by the KVM accelerator,
>>> but I'd say it is a generic feature.
>>>
>>
>> Maybe in the future it will be a generic feature, and we can export it the right way?
>> It will be super-easy if the feature is well contained.
>>
>> Until it really is generic though, should it really appear in the middle of x86_cpu_realizefn?
>> currently the generic code in target/i386/cpu.c contains an unconditional call to:
>>
>> x86_cpu_hyperv_realize(cpu);
>>
>> before the call to cpu_exec_realizefn().
>>
>> the function is defined in this very same file before as:
>>
>> static void x86_cpu_hyperv_realize(X86CPU *cpu)
>> {
>>  ...
>> }
>>
>> with a bunch of initializations of hyperv specific data, for example cpu->hyperv_interface_id, cpu->hyperv_vendor_id, cpu->hyperv_version_id.
>>
>> That data is ever only used in kvm/kvm.c, which is built conditionally under CONFIG_KVM.
>>
>> So the existing situation is fairly inconsistent in my view, at least for how things are now, and in principle the extra code of the initializations for hyperv should never be executed if !CONFIG_KVM.
> 
> What's the problem you are trying to solve?  Speed?  Binary size?
> Something else?
> 
> Moving the code in x86_cpu_hyperv_realize() to kvm-cpu.c sounds
> like a drop in the bucket.  It wouldn't get rid of
> hyperv-specific code in cpu.c, which includes:
> - the "hv-*" properties in x86_cpu_properties[];
> - FEAT_HYPERV_* CPUID leaf definitions;
> - hyperv code in x86_cpu_get_crash_info().
> 
> I wouldn't object if somebody really wants to move it, but I
> don't see it as a problem.
> 

Nm I'll take a look later on.

Thanks!

Claudio
diff mbox series

Patch

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 343e51baab..ad9ef559fc 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1659,11 +1659,12 @@  struct X86CPU {
     uint64_t ucode_rev;
 
     uint32_t hyperv_spinlock_attempts;
-    char *hyperv_vendor_id;
+    char *hyperv_vendor;
     bool hyperv_synic_kvm_only;
     uint64_t hyperv_features;
     bool hyperv_passthrough;
     OnOffAuto hyperv_no_nonarch_cs;
+    uint32_t hyperv_vendor_id[3];
 
     bool check_cpuid;
     bool enforce_cpuid;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 77f0e44df8..599526406a 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6544,6 +6544,25 @@  static void x86_cpu_filter_features(X86CPU *cpu, bool verbose)
     }
 }
 
+static void x86_cpu_hyperv_realize(X86CPU *cpu)
+{
+    size_t len;
+
+    /* Hyper-V vendor id */
+    if (!cpu->hyperv_vendor) {
+        memcpy(cpu->hyperv_vendor_id, "Microsoft Hv", 12);
+    } else {
+        len = strlen(cpu->hyperv_vendor);
+
+        if (len > 12) {
+            warn_report("hv-vendor-id truncated to 12 characters");
+            len = 12;
+        }
+        memset(cpu->hyperv_vendor_id, 0, 12);
+        memcpy(cpu->hyperv_vendor_id, cpu->hyperv_vendor, len);
+    }
+}
+
 static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     CPUState *cs = CPU(dev);
@@ -6715,6 +6734,8 @@  static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
         env->cache_info_amd.l3_cache = &legacy_l3_cache;
     }
 
+    /* Process Hyper-V enlightenments */
+    x86_cpu_hyperv_realize(cpu);
 
     cpu_exec_realizefn(cs, &local_err);
     if (local_err != NULL) {
@@ -7218,7 +7239,7 @@  static Property x86_cpu_properties[] = {
     DEFINE_PROP_UINT32("min-xlevel2", X86CPU, env.cpuid_min_xlevel2, 0),
     DEFINE_PROP_UINT64("ucode-rev", X86CPU, ucode_rev, 0),
     DEFINE_PROP_BOOL("full-cpuid-auto-level", X86CPU, full_cpuid_auto_level, true),
-    DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
+    DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor),
     DEFINE_PROP_BOOL("cpuid-0xb", X86CPU, enable_cpuid_0xb, true),
     DEFINE_PROP_BOOL("lmce", X86CPU, enable_lmce, false),
     DEFINE_PROP_BOOL("l3-cache", X86CPU, enable_l3_cache, true),
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index bcfa4b03e0..6a5d91e39f 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -1208,6 +1208,13 @@  static int hyperv_handle_properties(CPUState *cs,
         memcpy(cpuid_ent, &cpuid->entries[0],
                cpuid->nent * sizeof(cpuid->entries[0]));
 
+        c = cpuid_find_entry(cpuid, HV_CPUID_VENDOR_AND_MAX_FUNCTIONS, 0);
+        if (c) {
+            cpu->hyperv_vendor_id[0] = c->ebx;
+            cpu->hyperv_vendor_id[1] = c->ecx;
+            cpu->hyperv_vendor_id[2] = c->edx;
+        }
+
         c = cpuid_find_entry(cpuid, HV_CPUID_FEATURES, 0);
         if (c) {
             env->features[FEAT_HYPERV_EAX] = c->eax;
@@ -1282,23 +1289,11 @@  static int hyperv_handle_properties(CPUState *cs,
 
     c = &cpuid_ent[cpuid_i++];
     c->function = HV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
-    if (!cpu->hyperv_vendor_id) {
-        memcpy(signature, "Microsoft Hv", 12);
-    } else {
-        size_t len = strlen(cpu->hyperv_vendor_id);
-
-        if (len > 12) {
-            error_report("hv-vendor-id truncated to 12 characters");
-            len = 12;
-        }
-        memset(signature, 0, 12);
-        memcpy(signature, cpu->hyperv_vendor_id, len);
-    }
     c->eax = hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS) ?
         HV_CPUID_NESTED_FEATURES : HV_CPUID_IMPLEMENT_LIMITS;
-    c->ebx = signature[0];
-    c->ecx = signature[1];
-    c->edx = signature[2];
+    c->ebx = cpu->hyperv_vendor_id[0];
+    c->ecx = cpu->hyperv_vendor_id[1];
+    c->edx = cpu->hyperv_vendor_id[2];
 
     c = &cpuid_ent[cpuid_i++];
     c->function = HV_CPUID_INTERFACE;