Patchwork [2/2,RFC,v2,2/2] hyper-v: initialize Hyper-V CPUID leaves.

login
register
mail settings
Submitter Vadim Rozenfeld
Date Oct. 23, 2011, 3:39 p.m.
Message ID <1319384389-1389-3-git-send-email-vrozenfe@redhat.com>
Download mbox | patch
Permalink /patch/121237/
State New
Headers show

Comments

Vadim Rozenfeld - Oct. 23, 2011, 3:39 p.m.
---
 target-i386/kvm.c |   73 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 71 insertions(+), 2 deletions(-)
Jan Kiszka - Dec. 1, 2011, 2:52 p.m.
On 2011-10-23 17:39, Vadim Rozenfeld wrote:
> ---
>  target-i386/kvm.c |   73 +++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 71 insertions(+), 2 deletions(-)
> 
> diff --git a/target-i386/kvm.c b/target-i386/kvm.c
> index 82fec8c..c061e3b 100644
> --- a/target-i386/kvm.c
> +++ b/target-i386/kvm.c
> @@ -29,6 +29,7 @@
>  #include "hw/pc.h"
>  #include "hw/apic.h"
>  #include "ioport.h"
> +#include "hyperv.h"
>  
>  //#define DEBUG_KVM
>  
> @@ -380,11 +381,16 @@ int kvm_arch_init_vcpu(CPUState *env)
>      cpuid_i = 0;
>  
>      /* Paravirtualization CPUIDs */
> -    memcpy(signature, "KVMKVMKVM\0\0\0", 12);
>      c = &cpuid_data.entries[cpuid_i++];
>      memset(c, 0, sizeof(*c));
>      c->function = KVM_CPUID_SIGNATURE;
> -    c->eax = 0;
> +    if (!hyperv_enabled()) {
> +        memcpy(signature, "KVMKVMKVM\0\0\0", 12);
> +        c->eax = 0;
> +    } else {
> +        memcpy(signature, "Microsoft Hv", 12);
> +        c->eax = HYPERV_CPUID_MIN;
> +    }
>      c->ebx = signature[0];
>      c->ecx = signature[1];
>      c->edx = signature[2];
> @@ -395,6 +401,54 @@ int kvm_arch_init_vcpu(CPUState *env)
>      c->eax = env->cpuid_kvm_features &
>          kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
>  
> +    if (hyperv_enabled()) {
> +        memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12);
> +        c->eax = signature[0];
> +
> +        c = &cpuid_data.entries[cpuid_i++];
> +        memset(c, 0, sizeof(*c));
> +        c->function = HYPERV_CPUID_VERSION;
> +        c->eax = 0x00001bbc;
> +        c->ebx = 0x00060001;
> +
> +        c = &cpuid_data.entries[cpuid_i++];
> +        memset(c, 0, sizeof(*c));
> +        c->function = HYPERV_CPUID_FEATURES;
> +        if (hyperv_relaxed_timing_enabled()) {
> +            c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
> +        }
> +        if (hyperv_vapic_recommended()) {
> +            c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
> +            c->eax |= HV_X64_MSR_APIC_ACCESS_AVAILABLE;
> +        }
> +
> +        c = &cpuid_data.entries[cpuid_i++];
> +        memset(c, 0, sizeof(*c));
> +        c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
> +        if (hyperv_relaxed_timing_enabled()) {
> +            c->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED;
> +        }
> +        if (hyperv_vapic_recommended()) {
> +            c->eax |= HV_X64_APIC_ACCESS_RECOMMENDED;
> +        }
> +        c->ebx = hyperv_get_spinlock_retries();
> +
> +        c = &cpuid_data.entries[cpuid_i++];
> +        memset(c, 0, sizeof(*c));
> +        c->function = HYPERV_CPUID_IMPLEMENT_LIMITS;
> +        c->eax = 0x40;
> +        c->ebx = 0x40;
> +
> +        c = &cpuid_data.entries[cpuid_i++];
> +        memset(c, 0, sizeof(*c));
> +        c->function = KVM_CPUID_SIGNATURE_NEXT;
> +        memcpy(signature, "KVMKVMKVM\0\0\0", 12);
> +        c->eax = 0;
> +        c->ebx = signature[0];
> +        c->ecx = signature[1];
> +        c->edx = signature[2];
> +    }
> +
>      has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);
>  
>      cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
> @@ -953,6 +1007,13 @@ static int kvm_put_msrs(CPUState *env, int level)
>              kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN,
>                                env->async_pf_en_msr);
>          }
> +        if (hyperv_hypercall_available()) {
> +            kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0);
> +            kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0);
> +        }
> +        if (hyperv_vapic_recommended()) {
> +            kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, 0);
> +        }
>      }
>      if (env->mcg_cap) {
>          int i;
> @@ -1190,6 +1251,14 @@ static int kvm_get_msrs(CPUState *env)
>          msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
>      }
>  
> +    if (hyperv_hypercall_available()) {
> +        msrs[n++].index = HV_X64_MSR_GUEST_OS_ID;
> +        msrs[n++].index = HV_X64_MSR_HYPERCALL;
> +    }
> +    if (hyperv_vapic_recommended()) {
> +        msrs[n++].index = HV_X64_MSR_APIC_ASSIST_PAGE;
> +    }
> +
>      if (env->mcg_cap) {
>          msrs[n++].index = MSR_MCG_STATUS;
>          msrs[n++].index = MSR_MCG_CTL;

Not sure if we discussed this already: Is there no need to save/restore
the HV MSR values in the vcpu structure? Specifcially kvm_get_msrs looks
fishy as you request to read the state from the kernel but then simply
ignore it.

Jan
Vadim Rozenfeld - Dec. 14, 2011, 5:33 p.m.
On Thu, 2011-12-01 at 15:52 +0100, Jan Kiszka wrote:
> On 2011-10-23 17:39, Vadim Rozenfeld wrote:
> > ---
> >  target-i386/kvm.c |   73 +++++++++++++++++++++++++++++++++++++++++++++++++++-
> >  1 files changed, 71 insertions(+), 2 deletions(-)
> > 
> > diff --git a/target-i386/kvm.c b/target-i386/kvm.c
> > index 82fec8c..c061e3b 100644
> > --- a/target-i386/kvm.c
> > +++ b/target-i386/kvm.c
> > @@ -29,6 +29,7 @@
> >  #include "hw/pc.h"
> >  #include "hw/apic.h"
> >  #include "ioport.h"
> > +#include "hyperv.h"
> >  
> >  //#define DEBUG_KVM
> >  
> > @@ -380,11 +381,16 @@ int kvm_arch_init_vcpu(CPUState *env)
> >      cpuid_i = 0;
> >  
> >      /* Paravirtualization CPUIDs */
> > -    memcpy(signature, "KVMKVMKVM\0\0\0", 12);
> >      c = &cpuid_data.entries[cpuid_i++];
> >      memset(c, 0, sizeof(*c));
> >      c->function = KVM_CPUID_SIGNATURE;
> > -    c->eax = 0;
> > +    if (!hyperv_enabled()) {
> > +        memcpy(signature, "KVMKVMKVM\0\0\0", 12);
> > +        c->eax = 0;
> > +    } else {
> > +        memcpy(signature, "Microsoft Hv", 12);
> > +        c->eax = HYPERV_CPUID_MIN;
> > +    }
> >      c->ebx = signature[0];
> >      c->ecx = signature[1];
> >      c->edx = signature[2];
> > @@ -395,6 +401,54 @@ int kvm_arch_init_vcpu(CPUState *env)
> >      c->eax = env->cpuid_kvm_features &
> >          kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
> >  
> > +    if (hyperv_enabled()) {
> > +        memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12);
> > +        c->eax = signature[0];
> > +
> > +        c = &cpuid_data.entries[cpuid_i++];
> > +        memset(c, 0, sizeof(*c));
> > +        c->function = HYPERV_CPUID_VERSION;
> > +        c->eax = 0x00001bbc;
> > +        c->ebx = 0x00060001;
> > +
> > +        c = &cpuid_data.entries[cpuid_i++];
> > +        memset(c, 0, sizeof(*c));
> > +        c->function = HYPERV_CPUID_FEATURES;
> > +        if (hyperv_relaxed_timing_enabled()) {
> > +            c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
> > +        }
> > +        if (hyperv_vapic_recommended()) {
> > +            c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
> > +            c->eax |= HV_X64_MSR_APIC_ACCESS_AVAILABLE;
> > +        }
> > +
> > +        c = &cpuid_data.entries[cpuid_i++];
> > +        memset(c, 0, sizeof(*c));
> > +        c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
> > +        if (hyperv_relaxed_timing_enabled()) {
> > +            c->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED;
> > +        }
> > +        if (hyperv_vapic_recommended()) {
> > +            c->eax |= HV_X64_APIC_ACCESS_RECOMMENDED;
> > +        }
> > +        c->ebx = hyperv_get_spinlock_retries();
> > +
> > +        c = &cpuid_data.entries[cpuid_i++];
> > +        memset(c, 0, sizeof(*c));
> > +        c->function = HYPERV_CPUID_IMPLEMENT_LIMITS;
> > +        c->eax = 0x40;
> > +        c->ebx = 0x40;
> > +
> > +        c = &cpuid_data.entries[cpuid_i++];
> > +        memset(c, 0, sizeof(*c));
> > +        c->function = KVM_CPUID_SIGNATURE_NEXT;
> > +        memcpy(signature, "KVMKVMKVM\0\0\0", 12);
> > +        c->eax = 0;
> > +        c->ebx = signature[0];
> > +        c->ecx = signature[1];
> > +        c->edx = signature[2];
> > +    }
> > +
> >      has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);
> >  
> >      cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
> > @@ -953,6 +1007,13 @@ static int kvm_put_msrs(CPUState *env, int level)
> >              kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN,
> >                                env->async_pf_en_msr);
> >          }
> > +        if (hyperv_hypercall_available()) {
> > +            kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0);
> > +            kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0);
> > +        }
> > +        if (hyperv_vapic_recommended()) {
> > +            kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, 0);
> > +        }
> >      }
> >      if (env->mcg_cap) {
> >          int i;
> > @@ -1190,6 +1251,14 @@ static int kvm_get_msrs(CPUState *env)
> >          msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
> >      }
> >  
> > +    if (hyperv_hypercall_available()) {
> > +        msrs[n++].index = HV_X64_MSR_GUEST_OS_ID;
> > +        msrs[n++].index = HV_X64_MSR_HYPERCALL;
> > +    }
> > +    if (hyperv_vapic_recommended()) {
> > +        msrs[n++].index = HV_X64_MSR_APIC_ASSIST_PAGE;
> > +    }
> > +
> >      if (env->mcg_cap) {
> >          msrs[n++].index = MSR_MCG_STATUS;
> >          msrs[n++].index = MSR_MCG_CTL;
> 
> Not sure if we discussed this already: Is there no need to save/restore
> the HV MSR values in the vcpu structure? Specifcially kvm_get_msrs looks
> fishy as you request to read the state from the kernel but then simply
> ignore it.

You're right. We don't need to keep hyper-v msrs in the vcpu structure
at the moment. I will revert kvm_get_msrs changes back to the original
state.
Vadim. 
> 
> Jan
>

Patch

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 82fec8c..c061e3b 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -29,6 +29,7 @@ 
 #include "hw/pc.h"
 #include "hw/apic.h"
 #include "ioport.h"
+#include "hyperv.h"
 
 //#define DEBUG_KVM
 
@@ -380,11 +381,16 @@  int kvm_arch_init_vcpu(CPUState *env)
     cpuid_i = 0;
 
     /* Paravirtualization CPUIDs */
-    memcpy(signature, "KVMKVMKVM\0\0\0", 12);
     c = &cpuid_data.entries[cpuid_i++];
     memset(c, 0, sizeof(*c));
     c->function = KVM_CPUID_SIGNATURE;
-    c->eax = 0;
+    if (!hyperv_enabled()) {
+        memcpy(signature, "KVMKVMKVM\0\0\0", 12);
+        c->eax = 0;
+    } else {
+        memcpy(signature, "Microsoft Hv", 12);
+        c->eax = HYPERV_CPUID_MIN;
+    }
     c->ebx = signature[0];
     c->ecx = signature[1];
     c->edx = signature[2];
@@ -395,6 +401,54 @@  int kvm_arch_init_vcpu(CPUState *env)
     c->eax = env->cpuid_kvm_features &
         kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
 
+    if (hyperv_enabled()) {
+        memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12);
+        c->eax = signature[0];
+
+        c = &cpuid_data.entries[cpuid_i++];
+        memset(c, 0, sizeof(*c));
+        c->function = HYPERV_CPUID_VERSION;
+        c->eax = 0x00001bbc;
+        c->ebx = 0x00060001;
+
+        c = &cpuid_data.entries[cpuid_i++];
+        memset(c, 0, sizeof(*c));
+        c->function = HYPERV_CPUID_FEATURES;
+        if (hyperv_relaxed_timing_enabled()) {
+            c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
+        }
+        if (hyperv_vapic_recommended()) {
+            c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
+            c->eax |= HV_X64_MSR_APIC_ACCESS_AVAILABLE;
+        }
+
+        c = &cpuid_data.entries[cpuid_i++];
+        memset(c, 0, sizeof(*c));
+        c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
+        if (hyperv_relaxed_timing_enabled()) {
+            c->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED;
+        }
+        if (hyperv_vapic_recommended()) {
+            c->eax |= HV_X64_APIC_ACCESS_RECOMMENDED;
+        }
+        c->ebx = hyperv_get_spinlock_retries();
+
+        c = &cpuid_data.entries[cpuid_i++];
+        memset(c, 0, sizeof(*c));
+        c->function = HYPERV_CPUID_IMPLEMENT_LIMITS;
+        c->eax = 0x40;
+        c->ebx = 0x40;
+
+        c = &cpuid_data.entries[cpuid_i++];
+        memset(c, 0, sizeof(*c));
+        c->function = KVM_CPUID_SIGNATURE_NEXT;
+        memcpy(signature, "KVMKVMKVM\0\0\0", 12);
+        c->eax = 0;
+        c->ebx = signature[0];
+        c->ecx = signature[1];
+        c->edx = signature[2];
+    }
+
     has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);
 
     cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
@@ -953,6 +1007,13 @@  static int kvm_put_msrs(CPUState *env, int level)
             kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN,
                               env->async_pf_en_msr);
         }
+        if (hyperv_hypercall_available()) {
+            kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0);
+            kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0);
+        }
+        if (hyperv_vapic_recommended()) {
+            kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, 0);
+        }
     }
     if (env->mcg_cap) {
         int i;
@@ -1190,6 +1251,14 @@  static int kvm_get_msrs(CPUState *env)
         msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
     }
 
+    if (hyperv_hypercall_available()) {
+        msrs[n++].index = HV_X64_MSR_GUEST_OS_ID;
+        msrs[n++].index = HV_X64_MSR_HYPERCALL;
+    }
+    if (hyperv_vapic_recommended()) {
+        msrs[n++].index = HV_X64_MSR_APIC_ASSIST_PAGE;
+    }
+
     if (env->mcg_cap) {
         msrs[n++].index = MSR_MCG_STATUS;
         msrs[n++].index = MSR_MCG_CTL;