i386: expand Hyper-V features during CPU feature expansion time

To make Hyper-V features appear in e.g. QMP query-cpu-model-expansion we
need to expand and set the corresponding CPUID leaves early. Modify
x86_cpu_get_supported_feature_word() to call newly intoduced Hyper-V
specific kvm_hv_get_supported_cpuid() instead of
kvm_arch_get_supported_cpuid(). We can't use kvm_arch_get_supported_cpuid()
as Hyper-V specific CPUID leaves intersect with KVM's.

Note, early expansion will only happen when KVM supports system wide
KVM_GET_SUPPORTED_HV_CPUID ioctl (KVM_CAP_SYS_HYPERV_CPUID).

Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20210608120817.1325125-6-vkuznets@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
Vitaly Kuznetsov 2021-06-08 14:08:13 +02:00 committed by Eduardo Habkost
parent d7652b772f
commit 071ce4b03b
4 changed files with 30 additions and 4 deletions

View File

@ -5974,6 +5974,10 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
if (env->cpuid_xlevel2 == UINT32_MAX) {
env->cpuid_xlevel2 = env->cpuid_min_xlevel2;
}
if (kvm_enabled()) {
kvm_hyperv_expand_features(cpu, errp);
}
}
/*

View File

@ -39,3 +39,8 @@ bool kvm_hv_vpindex_settable(void)
{
return false;
}
bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp)
{
abort();
}

View File

@ -1220,13 +1220,22 @@ static uint32_t hv_build_cpuid_leaf(CPUState *cs, uint32_t func, int reg)
* of 'hv_passthrough' mode and fills the environment with all supported
* Hyper-V features.
*/
static bool hyperv_expand_features(CPUState *cs, Error **errp)
bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp)
{
X86CPU *cpu = X86_CPU(cs);
CPUState *cs = CPU(cpu);
if (!hyperv_enabled(cpu))
return true;
/*
* When kvm_hyperv_expand_features is called at CPU feature expansion
* time per-CPU kvm_state is not available yet so we can only proceed
* when KVM_CAP_SYS_HYPERV_CPUID is supported.
*/
if (!cs->kvm_state &&
!kvm_check_extension(kvm_state, KVM_CAP_SYS_HYPERV_CPUID))
return true;
if (cpu->hyperv_passthrough) {
cpu->hyperv_vendor_id[0] =
hv_cpuid_get_host(cs, HV_CPUID_VENDOR_AND_MAX_FUNCTIONS, R_EBX);
@ -1593,8 +1602,15 @@ int kvm_arch_init_vcpu(CPUState *cs)
env->apic_bus_freq = KVM_APIC_BUS_FREQUENCY;
/* Paravirtualization CPUIDs */
if (!hyperv_expand_features(cs, &local_err)) {
/*
* kvm_hyperv_expand_features() is called here for the second time in case
* KVM_CAP_SYS_HYPERV_CPUID is not supported. While we can't possibly handle
* 'query-cpu-model-expansion' in this case as we don't have a KVM vCPU to
* check which Hyper-V enlightenments are supported and which are not, we
* can still proceed and check/expand Hyper-V enlightenments here so legacy
* behavior is preserved.
*/
if (!kvm_hyperv_expand_features(cpu, &local_err)) {
error_report_err(local_err);
return -ENOSYS;
}

View File

@ -47,6 +47,7 @@ bool kvm_has_x2apic_api(void);
bool kvm_has_waitpkg(void);
bool kvm_hv_vpindex_settable(void);
bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp);
uint64_t kvm_swizzle_msi_ext_dest_id(uint64_t address);