diff mbox series

i386/kvm: Add CPU property to expose VMware CPUID signature

Message ID 20200310004017.100484-1-liran.alon@oracle.com
State New
Headers show
Series i386/kvm: Add CPU property to expose VMware CPUID signature | expand

Commit Message

Liran Alon March 10, 2020, 12:40 a.m. UTC
Some guests are only familiar with VMware PV interface. Therefore, in
order for these guests to run properly on KVM, we need to be able to
expose VMware main CPUID leaf. i.e. leaf 0x40000000.

E.g. Without exposing this VMware CPUID leaf, some guests will fail to boot.
For example, because of guest attempt to calibrate TSC.

Signed-off-by: Liran Alon <liran.alon@oracle.com>
---
 target/i386/cpu.c |  1 +
 target/i386/cpu.h |  1 +
 target/i386/kvm.c | 35 +++++++++++++++++++++++++++++------
 3 files changed, 31 insertions(+), 6 deletions(-)

Comments

Liran Alon March 17, 2020, 5:43 p.m. UTC | #1
Gentle ping (A week have passed since submission).

Thanks,
-Liran

On 10/03/2020 2:40, Liran Alon wrote:
> Some guests are only familiar with VMware PV interface. Therefore, in
> order for these guests to run properly on KVM, we need to be able to
> expose VMware main CPUID leaf. i.e. leaf 0x40000000.
>
> E.g. Without exposing this VMware CPUID leaf, some guests will fail to boot.
> For example, because of guest attempt to calibrate TSC.
>
> Signed-off-by: Liran Alon <liran.alon@oracle.com>
> ---
>   target/i386/cpu.c |  1 +
>   target/i386/cpu.h |  1 +
>   target/i386/kvm.c | 35 +++++++++++++++++++++++++++++------
>   3 files changed, 31 insertions(+), 6 deletions(-)
>
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 92fafa265914..694766d45a9b 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -7127,6 +7127,7 @@ static Property x86_cpu_properties[] = {
>       DEFINE_PROP_BOOL("l3-cache", X86CPU, enable_l3_cache, true),
>       DEFINE_PROP_BOOL("kvm-no-smi-migration", X86CPU, kvm_no_smi_migration,
>                        false),
> +    DEFINE_PROP_BOOL("vmware-cpuid", X86CPU, expose_vmware, false),
>       DEFINE_PROP_BOOL("vmware-cpuid-freq", X86CPU, vmware_cpuid_freq, true),
>       DEFINE_PROP_BOOL("tcg-cpuid", X86CPU, expose_tcg, true),
>       DEFINE_PROP_BOOL("x-migrate-smi-count", X86CPU, migrate_smi_count,
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 9c7cd7cde107..bca626963e25 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -1647,6 +1647,7 @@ struct X86CPU {
>        */
>       bool force_features;
>       bool expose_kvm;
> +    bool expose_vmware;
>       bool expose_tcg;
>       bool migratable;
>       bool migrate_smi_count;
> diff --git a/target/i386/kvm.c b/target/i386/kvm.c
> index 00917196dffb..2656258b96b3 100644
> --- a/target/i386/kvm.c
> +++ b/target/i386/kvm.c
> @@ -1187,6 +1187,15 @@ static int hyperv_handle_properties(CPUState *cs,
>       if (!hyperv_enabled(cpu))
>           return 0;
>   
> +    /*
> +     * VMware & Hyper-V conflicts in CPUID leafs.
> +     * Therefore, they cannot exists together.
> +     */
> +    if (cpu->expose_vmware) {
> +        error_report("vmware-cpuid not compatible with hyperv options");
> +        return -ENOTSUP;
> +    }
> +
>       if (hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS) ||
>           cpu->hyperv_passthrough) {
>           uint16_t evmcs_version;
> @@ -1508,6 +1517,18 @@ int kvm_arch_init_vcpu(CPUState *cs)
>           has_msr_hv_hypercall = true;
>       }
>   
> +    if (cpu->expose_vmware) {
> +        c = &cpuid_data.entries[cpuid_i++];
> +        c->function = KVM_CPUID_SIGNATURE;
> +        memcpy(signature, "VMwareVMware", 12);
> +        c->eax = KVM_CPUID_SIGNATURE;
> +        c->ebx = signature[0];
> +        c->ecx = signature[1];
> +        c->edx = signature[2];
> +
> +        kvm_base = KVM_CPUID_SIGNATURE_NEXT;
> +    }
> +
>       if (cpu->expose_kvm) {
>           memcpy(signature, "KVMKVMKVM\0\0\0", 12);
>           c = &cpuid_data.entries[cpuid_i++];
> @@ -1791,11 +1812,13 @@ int kvm_arch_init_vcpu(CPUState *cs)
>           }
>       }
>   
> -    if (cpu->vmware_cpuid_freq
> -        /* Guests depend on 0x40000000 to detect this feature, so only expose
> -         * it if KVM exposes leaf 0x40000000. (Conflicts with Hyper-V) */
> -        && cpu->expose_kvm
> -        && kvm_base == KVM_CPUID_SIGNATURE
> +    if (cpu->vmware_cpuid_freq &&
> +        (cpu->expose_vmware ||
> +         /*
> +          * Guests depend on 0x40000000 to detect this feature, so only expose
> +          * it if KVM exposes leaf 0x40000000. (Conflicts with Hyper-V)
> +          */
> +          (cpu->expose_kvm && kvm_base == KVM_CPUID_SIGNATURE))
>           /* TSC clock must be stable and known for this feature. */
>           && tsc_is_stable_and_known(env)) {
>   
> @@ -1805,7 +1828,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
>           c->ebx = env->apic_bus_freq / 1000; /* Hz to KHz */
>           c->ecx = c->edx = 0;
>   
> -        c = cpuid_find_entry(&cpuid_data.cpuid, kvm_base, 0);
> +        c = cpuid_find_entry(&cpuid_data.cpuid, KVM_CPUID_SIGNATURE, 0);
>           c->eax = MAX(c->eax, KVM_CPUID_SIGNATURE | 0x10);
>       }
>
Paolo Bonzini March 17, 2020, 6:02 p.m. UTC | #2
On 10/03/20 01:40, Liran Alon wrote:
> Some guests are only familiar with VMware PV interface. Therefore, in
> order for these guests to run properly on KVM, we need to be able to
> expose VMware main CPUID leaf. i.e. leaf 0x40000000.
> 
> E.g. Without exposing this VMware CPUID leaf, some guests will fail to boot.
> For example, because of guest attempt to calibrate TSC.
> 
> Signed-off-by: Liran Alon <liran.alon@oracle.com>

Looks good, thanks.  It was submitted quite close to soft freeze so I
couldn't get to it quickly.  But I've queued it now, either for 5.0 or 5.1.

Paolo

> ---
>  target/i386/cpu.c |  1 +
>  target/i386/cpu.h |  1 +
>  target/i386/kvm.c | 35 +++++++++++++++++++++++++++++------
>  3 files changed, 31 insertions(+), 6 deletions(-)
> 
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 92fafa265914..694766d45a9b 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -7127,6 +7127,7 @@ static Property x86_cpu_properties[] = {
>      DEFINE_PROP_BOOL("l3-cache", X86CPU, enable_l3_cache, true),
>      DEFINE_PROP_BOOL("kvm-no-smi-migration", X86CPU, kvm_no_smi_migration,
>                       false),
> +    DEFINE_PROP_BOOL("vmware-cpuid", X86CPU, expose_vmware, false),
>      DEFINE_PROP_BOOL("vmware-cpuid-freq", X86CPU, vmware_cpuid_freq, true),
>      DEFINE_PROP_BOOL("tcg-cpuid", X86CPU, expose_tcg, true),
>      DEFINE_PROP_BOOL("x-migrate-smi-count", X86CPU, migrate_smi_count,
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 9c7cd7cde107..bca626963e25 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -1647,6 +1647,7 @@ struct X86CPU {
>       */
>      bool force_features;
>      bool expose_kvm;
> +    bool expose_vmware;
>      bool expose_tcg;
>      bool migratable;
>      bool migrate_smi_count;
> diff --git a/target/i386/kvm.c b/target/i386/kvm.c
> index 00917196dffb..2656258b96b3 100644
> --- a/target/i386/kvm.c
> +++ b/target/i386/kvm.c
> @@ -1187,6 +1187,15 @@ static int hyperv_handle_properties(CPUState *cs,
>      if (!hyperv_enabled(cpu))
>          return 0;
>  
> +    /*
> +     * VMware & Hyper-V conflicts in CPUID leafs.
> +     * Therefore, they cannot exists together.
> +     */
> +    if (cpu->expose_vmware) {
> +        error_report("vmware-cpuid not compatible with hyperv options");
> +        return -ENOTSUP;
> +    }
> +
>      if (hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS) ||
>          cpu->hyperv_passthrough) {
>          uint16_t evmcs_version;
> @@ -1508,6 +1517,18 @@ int kvm_arch_init_vcpu(CPUState *cs)
>          has_msr_hv_hypercall = true;
>      }
>  
> +    if (cpu->expose_vmware) {
> +        c = &cpuid_data.entries[cpuid_i++];
> +        c->function = KVM_CPUID_SIGNATURE;
> +        memcpy(signature, "VMwareVMware", 12);
> +        c->eax = KVM_CPUID_SIGNATURE;
> +        c->ebx = signature[0];
> +        c->ecx = signature[1];
> +        c->edx = signature[2];
> +
> +        kvm_base = KVM_CPUID_SIGNATURE_NEXT;
> +    }
> +
>      if (cpu->expose_kvm) {
>          memcpy(signature, "KVMKVMKVM\0\0\0", 12);
>          c = &cpuid_data.entries[cpuid_i++];
> @@ -1791,11 +1812,13 @@ int kvm_arch_init_vcpu(CPUState *cs)
>          }
>      }
>  
> -    if (cpu->vmware_cpuid_freq
> -        /* Guests depend on 0x40000000 to detect this feature, so only expose
> -         * it if KVM exposes leaf 0x40000000. (Conflicts with Hyper-V) */
> -        && cpu->expose_kvm
> -        && kvm_base == KVM_CPUID_SIGNATURE
> +    if (cpu->vmware_cpuid_freq &&
> +        (cpu->expose_vmware ||
> +         /*
> +          * Guests depend on 0x40000000 to detect this feature, so only expose
> +          * it if KVM exposes leaf 0x40000000. (Conflicts with Hyper-V)
> +          */
> +          (cpu->expose_kvm && kvm_base == KVM_CPUID_SIGNATURE))
>          /* TSC clock must be stable and known for this feature. */
>          && tsc_is_stable_and_known(env)) {
>  
> @@ -1805,7 +1828,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
>          c->ebx = env->apic_bus_freq / 1000; /* Hz to KHz */
>          c->ecx = c->edx = 0;
>  
> -        c = cpuid_find_entry(&cpuid_data.cpuid, kvm_base, 0);
> +        c = cpuid_find_entry(&cpuid_data.cpuid, KVM_CPUID_SIGNATURE, 0);
>          c->eax = MAX(c->eax, KVM_CPUID_SIGNATURE | 0x10);
>      }
>  
>
diff mbox series

Patch

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 92fafa265914..694766d45a9b 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -7127,6 +7127,7 @@  static Property x86_cpu_properties[] = {
     DEFINE_PROP_BOOL("l3-cache", X86CPU, enable_l3_cache, true),
     DEFINE_PROP_BOOL("kvm-no-smi-migration", X86CPU, kvm_no_smi_migration,
                      false),
+    DEFINE_PROP_BOOL("vmware-cpuid", X86CPU, expose_vmware, false),
     DEFINE_PROP_BOOL("vmware-cpuid-freq", X86CPU, vmware_cpuid_freq, true),
     DEFINE_PROP_BOOL("tcg-cpuid", X86CPU, expose_tcg, true),
     DEFINE_PROP_BOOL("x-migrate-smi-count", X86CPU, migrate_smi_count,
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 9c7cd7cde107..bca626963e25 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1647,6 +1647,7 @@  struct X86CPU {
      */
     bool force_features;
     bool expose_kvm;
+    bool expose_vmware;
     bool expose_tcg;
     bool migratable;
     bool migrate_smi_count;
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 00917196dffb..2656258b96b3 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -1187,6 +1187,15 @@  static int hyperv_handle_properties(CPUState *cs,
     if (!hyperv_enabled(cpu))
         return 0;
 
+    /*
+     * VMware & Hyper-V conflicts in CPUID leafs.
+     * Therefore, they cannot exists together.
+     */
+    if (cpu->expose_vmware) {
+        error_report("vmware-cpuid not compatible with hyperv options");
+        return -ENOTSUP;
+    }
+
     if (hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS) ||
         cpu->hyperv_passthrough) {
         uint16_t evmcs_version;
@@ -1508,6 +1517,18 @@  int kvm_arch_init_vcpu(CPUState *cs)
         has_msr_hv_hypercall = true;
     }
 
+    if (cpu->expose_vmware) {
+        c = &cpuid_data.entries[cpuid_i++];
+        c->function = KVM_CPUID_SIGNATURE;
+        memcpy(signature, "VMwareVMware", 12);
+        c->eax = KVM_CPUID_SIGNATURE;
+        c->ebx = signature[0];
+        c->ecx = signature[1];
+        c->edx = signature[2];
+
+        kvm_base = KVM_CPUID_SIGNATURE_NEXT;
+    }
+
     if (cpu->expose_kvm) {
         memcpy(signature, "KVMKVMKVM\0\0\0", 12);
         c = &cpuid_data.entries[cpuid_i++];
@@ -1791,11 +1812,13 @@  int kvm_arch_init_vcpu(CPUState *cs)
         }
     }
 
-    if (cpu->vmware_cpuid_freq
-        /* Guests depend on 0x40000000 to detect this feature, so only expose
-         * it if KVM exposes leaf 0x40000000. (Conflicts with Hyper-V) */
-        && cpu->expose_kvm
-        && kvm_base == KVM_CPUID_SIGNATURE
+    if (cpu->vmware_cpuid_freq &&
+        (cpu->expose_vmware ||
+         /*
+          * Guests depend on 0x40000000 to detect this feature, so only expose
+          * it if KVM exposes leaf 0x40000000. (Conflicts with Hyper-V)
+          */
+          (cpu->expose_kvm && kvm_base == KVM_CPUID_SIGNATURE))
         /* TSC clock must be stable and known for this feature. */
         && tsc_is_stable_and_known(env)) {
 
@@ -1805,7 +1828,7 @@  int kvm_arch_init_vcpu(CPUState *cs)
         c->ebx = env->apic_bus_freq / 1000; /* Hz to KHz */
         c->ecx = c->edx = 0;
 
-        c = cpuid_find_entry(&cpuid_data.cpuid, kvm_base, 0);
+        c = cpuid_find_entry(&cpuid_data.cpuid, KVM_CPUID_SIGNATURE, 0);
         c->eax = MAX(c->eax, KVM_CPUID_SIGNATURE | 0x10);
     }