From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49112) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bIf1W-0002v2-57 for qemu-devel@nongnu.org; Thu, 30 Jun 2016 12:41:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bIf1S-0002L7-Ub for qemu-devel@nongnu.org; Thu, 30 Jun 2016 12:41:06 -0400 Received: from mail-db5eur01on0130.outbound.protection.outlook.com ([104.47.2.130]:29216 helo=EUR01-DB5-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bIf1S-0002Kq-B3 for qemu-devel@nongnu.org; Thu, 30 Jun 2016 12:41:02 -0400 References: <1466765376-25722-1-git-send-email-den@openvz.org> From: "Denis V. Lunev" Message-ID: <577547FA.7050805@openvz.org> Date: Thu, 30 Jun 2016 19:25:30 +0300 MIME-Version: 1.0 In-Reply-To: <1466765376-25722-1-git-send-email-den@openvz.org> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v3 1/1] cpu: report hyperv feature words through qom List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Evgeny Yakovlev , Paolo Bonzini , Richard Henderson , Eduardo Habkost , Marcelo Tosatti On 06/24/2016 01:49 PM, Denis V. Lunev wrote: > From: Evgeny Yakovlev > > 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. > > To avoid conflicting with current hyperv properties all added feature > words cannot be set directly with -cpu +feature yet. > > Signed-off-by: Evgeny Yakovlev > Signed-off-by: Denis V. Lunev > CC: Paolo Bonzini > CC: Richard Henderson > CC: Eduardo Habkost > CC: Marcelo Tosatti > --- > Changes from v2: > - removed all hyperv feature_names so that we don't have two ways of > setting CPUID bits > > 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 | 53 +++++++++++++++++++++++++ > target-i386/cpu.h | 3 ++ > target-i386/kvm.c | 114 +++++++++++++++++++++++++++++++----------------------- > 3 files changed, 122 insertions(+), 48 deletions(-) > > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > index 3bd3cfc..d07da78 100644 > --- a/target-i386/cpu.c > +++ b/target-i386/cpu.c > @@ -245,6 +245,47 @@ static const char *kvm_feature_name[] = { > NULL, NULL, NULL, NULL, > }; > > +static const char *hyperv_priv_feature_name[] = { > + NULL /* hv_msr_vp_runtime_access */, NULL /* hv_msr_time_refcount_access */, > + NULL /* hv_msr_synic_access */, NULL /* hv_msr_stimer_access */, > + NULL /* hv_msr_apic_access */, NULL /* hv_msr_hypercall_access */, > + NULL /* hv_vpindex_access */, NULL /* hv_msr_reset_access */, > + NULL /* hv_msr_stats_access */, NULL /* hv_reftsc_access */, > + NULL /* hv_msr_idle_access */, NULL /* 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[] = { > + NULL /* hv_create_partitions */, NULL /* hv_access_partition_id */, > + NULL /* hv_access_memory_pool */, NULL /* hv_adjust_message_buffers */, > + NULL /* hv_post_messages */, NULL /* hv_signal_events */, > + NULL /* hv_create_port */, NULL /* hv_connect_port */, > + NULL /* hv_access_stats */, NULL, NULL, NULL /* hv_debugging */, > + NULL /* hv_cpu_power_management */, NULL /* 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[] = { > + NULL /* hv_mwait */, NULL /* hv_guest_debugging */, > + NULL /* hv_perf_monitor */, NULL /* hv_cpu_dynamic_part */, > + NULL /* hv_hypercall_params_xmm */, NULL /* hv_guest_idle_state */, > + NULL, 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 +452,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 f3698f1..f44e3c7 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) { ping