qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 1/1] cpu: report hyperv feature words through qom
@ 2016-06-20 15:29 Denis V. Lunev
  2016-06-21 12:00 ` Paolo Bonzini
  2016-06-22 21:01 ` Eduardo Habkost
  0 siblings, 2 replies; 6+ messages in thread
From: Denis V. Lunev @ 2016-06-20 15:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: den, Evgeny Yakovlev, Paolo Bonzini, Richard Henderson,
	Eduardo Habkost, Marcelo Tosatti

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 feature 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>
---
Changes from v1:
- renamed hyperv features so they don't conflict with hyperv properties
- refactored kvm_arch_init_vcpu to process hyperv props into feature words

 target-i386/cpu.c |  50 ++++++++++++++++++++++++
 target-i386/cpu.h |   3 ++
 target-i386/kvm.c | 114 +++++++++++++++++++++++++++++++-----------------------
 3 files changed, 119 insertions(+), 48 deletions(-)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 3665fec..c79b4e3 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -245,6 +245,44 @@ static const char *kvm_feature_name[] = {
     NULL, NULL, NULL, NULL,
 };
 
+static const char *hyperv_priv_feature_name[] = {
+    "hv_msr_vp_runtime_access", "hv_msr_time_refcount_access",
+    "hv_msr_synic_access", "hv_msr_stimer_access",
+    "hv_msr_apic_access", "hv_msr_hypercall_access",
+    "hv_vpindex_access", "hv_msr_reset_access",
+    "hv_msr_stats_access", "hv_reftsc_access",
+    "hv_msr_idle_access", "hv_msr_frequency_access",
+    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",
@@ -411,6 +449,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 d9ab884..4496c8b 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 ff92b1d..5a3f14d 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -574,6 +574,66 @@ static int kvm_arch_set_tsc_khz(CPUState *cs)
     return 0;
 }
 
+static int hyperv_handle_properties(CPUState *cs)
+{
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
+    if (cpu->hyperv_relaxed_timing) {
+        env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_HYPERCALL_AVAILABLE;
+    }
+    if (cpu->hyperv_vapic) {
+        env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_HYPERCALL_AVAILABLE;
+        env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_APIC_ACCESS_AVAILABLE;
+        has_msr_hv_vapic = true;
+    }
+    if (cpu->hyperv_time &&
+            kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV_TIME) > 0) {
+        env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_HYPERCALL_AVAILABLE;
+        env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_TIME_REF_COUNT_AVAILABLE;
+        env->features[FEAT_HYPERV_EAX] |= 0x200;
+        has_msr_hv_tsc = true;
+    }
+    if (cpu->hyperv_crash && has_msr_hv_crash) {
+        env->features[FEAT_HYPERV_EDX] |= HV_X64_GUEST_CRASH_MSR_AVAILABLE;
+    }
+    if (cpu->hyperv_reset && has_msr_hv_reset) {
+        env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_RESET_AVAILABLE;
+    }
+    if (cpu->hyperv_vpindex && has_msr_hv_vpindex) {
+        env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_VP_INDEX_AVAILABLE;
+    }
+    if (cpu->hyperv_runtime && has_msr_hv_runtime) {
+        env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_VP_RUNTIME_AVAILABLE;
+    }
+    if (cpu->hyperv_synic) {
+        int sint;
+
+        if (!has_msr_hv_synic ||
+            kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_SYNIC, 0)) {
+            fprintf(stderr, "Hyper-V SynIC is not supported by kernel\n");
+            return -ENOSYS;
+        }
+
+        env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_SYNIC_AVAILABLE;
+        env->msr_hv_synic_version = HV_SYNIC_VERSION_1;
+        for (sint = 0; sint < ARRAY_SIZE(env->msr_hv_synic_sint); sint++) {
+            env->msr_hv_synic_sint[sint] = HV_SYNIC_SINT_MASKED;
+        }
+    }
+    if (cpu->hyperv_stimer) {
+        if (!has_msr_hv_stimer) {
+            fprintf(stderr, "Hyper-V timers aren't supported by kernel\n");
+            return -ENOSYS;
+        }
+        env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_SYNTIMER_AVAILABLE;
+    }
+    if (MACHINE_GET_CLASS(current_machine)->hot_add_cpu != NULL) {
+        env->features[FEAT_HYPERV_EDX] |= HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE;
+    }
+    return 0;
+}
+
 static Error *invtsc_mig_blocker;
 
 #define KVM_MAX_CPUID_ENTRIES  100
@@ -633,56 +693,14 @@ int kvm_arch_init_vcpu(CPUState *cs)
 
         c = &cpuid_data.entries[cpuid_i++];
         c->function = HYPERV_CPUID_FEATURES;
-        if (cpu->hyperv_relaxed_timing) {
-            c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
-        }
-        if (cpu->hyperv_vapic) {
-            c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
-            c->eax |= HV_X64_MSR_APIC_ACCESS_AVAILABLE;
-            has_msr_hv_vapic = true;
-        }
-        if (cpu->hyperv_time &&
-            kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV_TIME) > 0) {
-            c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
-            c->eax |= HV_X64_MSR_TIME_REF_COUNT_AVAILABLE;
-            c->eax |= 0x200;
-            has_msr_hv_tsc = true;
-        }
-        if (cpu->hyperv_crash && has_msr_hv_crash) {
-            c->edx |= HV_X64_GUEST_CRASH_MSR_AVAILABLE;
-        }
-        c->edx |= HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE;
-        if (cpu->hyperv_reset && has_msr_hv_reset) {
-            c->eax |= HV_X64_MSR_RESET_AVAILABLE;
-        }
-        if (cpu->hyperv_vpindex && has_msr_hv_vpindex) {
-            c->eax |= HV_X64_MSR_VP_INDEX_AVAILABLE;
-        }
-        if (cpu->hyperv_runtime && has_msr_hv_runtime) {
-            c->eax |= HV_X64_MSR_VP_RUNTIME_AVAILABLE;
+        r = hyperv_handle_properties(cs);
+        if (r) {
+            return r;
         }
-        if (cpu->hyperv_synic) {
-            int sint;
-
-            if (!has_msr_hv_synic ||
-                kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_SYNIC, 0)) {
-                fprintf(stderr, "Hyper-V SynIC is not supported by kernel\n");
-                return -ENOSYS;
-            }
+        c->eax = env->features[FEAT_HYPERV_EAX];
+        c->ebx = env->features[FEAT_HYPERV_EBX];
+        c->edx = env->features[FEAT_HYPERV_EDX];
 
-            c->eax |= HV_X64_MSR_SYNIC_AVAILABLE;
-            env->msr_hv_synic_version = HV_SYNIC_VERSION_1;
-            for (sint = 0; sint < ARRAY_SIZE(env->msr_hv_synic_sint); sint++) {
-                env->msr_hv_synic_sint[sint] = HV_SYNIC_SINT_MASKED;
-            }
-        }
-        if (cpu->hyperv_stimer) {
-            if (!has_msr_hv_stimer) {
-                fprintf(stderr, "Hyper-V timers aren't supported by kernel\n");
-                return -ENOSYS;
-            }
-            c->eax |= HV_X64_MSR_SYNTIMER_AVAILABLE;
-        }
         c = &cpuid_data.entries[cpuid_i++];
         c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
         if (cpu->hyperv_relaxed_timing) {
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-06-24 13:15 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-20 15:29 [Qemu-devel] [PATCH v2 1/1] cpu: report hyperv feature words through qom Denis V. Lunev
2016-06-21 12:00 ` Paolo Bonzini
2016-06-22 21:05   ` Eduardo Habkost
2016-06-22 21:01 ` Eduardo Habkost
2016-06-24 10:10   ` Evgeny Yakovlev
2016-06-24 13:15     ` Eduardo Habkost

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).