From: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
To: Eduardo Habkost <ehabkost@redhat.com>, "Denis V. Lunev" <den@openvz.org>
Cc: qemu-devel@nongnu.org, Paolo Bonzini <pbonzini@redhat.com>,
Richard Henderson <rth@twiddle.net>,
Marcelo Tosatti <mtosatti@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v2 1/1] cpu: report hyperv feature words through qom
Date: Fri, 24 Jun 2016 13:10:45 +0300 [thread overview]
Message-ID: <576D0725.7060003@virtuozzo.com> (raw)
In-Reply-To: <20160622210133.GP2048@thinpad.lan.raisama.net>
On 23.06.2016 00:01, Eduardo Habkost wrote:
> On Mon, Jun 20, 2016 at 06:29:40PM +0300, Denis V. Lunev wrote:
>> 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,
>> +};
> Adding these feature bit names will let individual bits to be
> configured from the command-line, not just reported using QOM.
>
> I am not sure this is intentional, as now we have conflicting
> ways to configure some hyperv features. For example: now
> HV_X64_MSR_VP_RUNTIME_AVAILABLE can be set using "+hv-runtime" or
> "+hv_msr_vp_runtime_access". And the difference between both
> methods is not clear for users.
>
> Also, as kvm_arch_get_supported_cpuid() won't return anything
> about those feature flags, QEMU will get confused if you try to
> use "+hv_msr_vp_runtime_access" in the command-line.
>
> I believe this can be addressed by doing the work in three steps:
>
> 1) Add hyperv CPUID leaves to FeatureWord/feature_word_info
> without any name arrays, make the changes you made below to
> change env->features inside kvm_arch_init_vcpu().
> * In other words: this patch, but without the feature_name
> arrays.
> * This wil make QEMU report all the hyperv feature bits in the
> "feature-words" QOM property (read-only)
> * This won't change any command-line interface.
> * This shouldn't confuse QEMU due to
> lack of kvm_arch_get_supported_cpuid() support, because
> env->features is being set up after
> x86_cpu_filter_features() was already called.
>
> If all you want is to report low-level CPUID data through QMP,
> step (1) is enough: it will already include the low-level hyperv
> CPUID data in the "feature-words" property.
>
> 2) Replace the hyperv_* boolean fields with env->feature bits.
> * See below how this could be done for each specific case.
> * This requires making kvm_arch_get_supported_cpuid() report
> them (after making the appropriate capability checks).
> * This makes the check/enforce flags support hyperv
> capabilities.
>
> 3) (optional) Add the remaining feature names (that are not
> configurable yet) to the feature_names arrays.
> * This won't let them be configured in the command-line by
> now, if kvm_arch_get_supported_cpuid() doesn't report them
> as supported.
> * I am not sure we really want that. What would be the point
> of adding feature names that we don't even support yet?
>
>> +
>> static const char *svm_feature_name[] = {
>> "npt", "lbrv", "svm_lock", "nrip_save",
>> "tsc_scale", "vmcb_clean", "flushbyasid", "decodeassists",
> [...]
>> 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;
>> + }
> HYPERV_CPUID_ENLIGHTMENT_INFO is not in FeatureWordInfo yet, so
> this looks OK by now.
>
>> + 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;
>> + }
> Now we can control HV_X64_MSR_APIC_ACCESS_AVAILABLE using
> "+hv-vapic" and "+hv_msr_apic_access", and the difference between
> both is unclear.
>
> I suggest the following:
>
> 1) Remove the "hv-vapic" static property from
> x86_cpu_properties, and the hyperv_vapic field
> 2) Change "hv_msr_apic_access" to "hv-vapic"
> in hyperv_priv_feature_name.
> 2) Replace code using cpu->hyperv_vapic with
> (env->features[FEAT_HYPERV_EAX] & HV_X64_MSR_APIC_ACCESS_AVAILABLE)
> 3) Change the setup code to:
>
> if (env->features[FEAT_HYPERV_EAX] & HV_X64_MSR_APIC_ACCESS_AVAILABLE) {
> env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_HYPERCALL_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;
>> + }
> This is similar to hyperv_vapic, but with the
> kvm_check_extension() check that needs to be moved to
> kvm_arch_get_supported_cpuid().
>
> I suggest:
>
> 1) Remove the "hv-time" static property from
> x86_cpu_properties, and the hyperv_time field
> 2) Change "hv_msr_time_refcount_access" to "hv-time"
> in hyperv_priv_feature_name.
> 2) Replace code using cpu->hyperv_time field with
> (env->features[FEAT_HYPERV_EAX] & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
> 3) Change the setup code to:
>
> if (env->features[FEAT_HYPERV_EAX] & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE) {
> env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_HYPERCALL_AVAILABLE;
> /*TODO: replace magic number with macro */
> env->features[FEAT_HYPERV_EAX] |= 0x200;
> has_msr_hv_tsc = true;
> }
>
> 4) Check KVM_CAP_HYPERV_TIME inside
> kvm_arch_get_supported_cpuid()
>
> This will add support for the check/enforce flags for hv-time
> automatically.
>
>
>> + if (cpu->hyperv_crash && has_msr_hv_crash) {
>> + env->features[FEAT_HYPERV_EDX] |= HV_X64_GUEST_CRASH_MSR_AVAILABLE;
>> + }
> This is similar to hv-time, if the has_msr_hv_crash check is
> moved to kvm_arch_get_supported_cpuid().
>
>> + if (cpu->hyperv_reset && has_msr_hv_reset) {
>> + env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_RESET_AVAILABLE;
>> + }
> This is similar to hv-time/hv-crash above.
>
>> + if (cpu->hyperv_vpindex && has_msr_hv_vpindex) {
>> + env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_VP_INDEX_AVAILABLE;
>> + }
> This is similar to hv-time/hv-crash above.
>
>> + if (cpu->hyperv_runtime && has_msr_hv_runtime) {
>> + env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_VP_RUNTIME_AVAILABLE;
>> + }
> Similar to hv-time/hv-crash.
>
>> + 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;
>> + }
>> + }
> This is a bit more complex, but the general idea is the same: add
> "hv-synic" to the feature name array, replace cpu->hyperv_synic
> with (env->features[FEAT_HYPERV_EAX] & HV_X64_MSR_SYNIC_AVAILABLE),
> move the capability check to kvm_arch_get_supported_cpuid(), keep
> the remaining setup code (for msr_hv_synic_*) here.
>
>> + 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;
>> + }
> Similar to hv-time/hv-crash.
>
> Interestingly, the last two features are the only ones that don't
> get silently disabled by the setup code if unsupported by KVM.
> Does anybody know why?
>
>> + if (MACHINE_GET_CLASS(current_machine)->hot_add_cpu != NULL) {
>> + env->features[FEAT_HYPERV_EDX] |= HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE;
>> + }
> This probably can be left as-is.
>
>> + 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_ENLIGHTMENT_INFO;
>> if (cpu->hyperv_relaxed_timing) {
> Do you plan to add HYPERV_CPUID_ENLIGHTMENT_INFO to
> FeatureWord/feature_word_info later?
>
Thanks for all the comments!
Removing hyperv_* booleans sounds like the proper way forward however it
will break compatibility with how libvirt enables hyperv enlightenments.
I think we will now concentrate on the QOM feature-words and later get
back to reworking hv_* properties. You suggestions will be very helpful
for that.
next prev parent reply other threads:[~2016-06-24 10:11 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
2016-06-24 13:15 ` Eduardo Habkost
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=576D0725.7060003@virtuozzo.com \
--to=eyakovlev@virtuozzo.com \
--cc=den@openvz.org \
--cc=ehabkost@redhat.com \
--cc=mtosatti@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).