i386: move eVMCS enablement to hyperv_init_vcpu()

hyperv_expand_features() will be called before we create vCPU so
evmcs enablement should go away. hyperv_init_vcpu() looks like the
right place.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <20210422161130.652779-11-vkuznets@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
Vitaly Kuznetsov 2021-04-22 18:11:21 +02:00 committed by Eduardo Habkost
parent f6e01ab563
commit decb4f2013
1 changed files with 37 additions and 23 deletions

View File

@ -963,6 +963,7 @@ static struct kvm_cpuid2 *get_supported_hv_cpuid(CPUState *cs)
{
struct kvm_cpuid2 *cpuid;
int max = 7; /* 0x40000000..0x40000005, 0x4000000A */
int i;
/*
* When the buffer is too small, KVM_GET_SUPPORTED_HV_CPUID fails with
@ -972,6 +973,22 @@ static struct kvm_cpuid2 *get_supported_hv_cpuid(CPUState *cs)
while ((cpuid = try_get_hv_cpuid(cs, max)) == NULL) {
max++;
}
/*
* KVM_GET_SUPPORTED_HV_CPUID does not set EVMCS CPUID bit before
* KVM_CAP_HYPERV_ENLIGHTENED_VMCS is enabled but we want to get the
* information early, just check for the capability and set the bit
* manually.
*/
if (kvm_check_extension(cs->kvm_state,
KVM_CAP_HYPERV_ENLIGHTENED_VMCS) > 0) {
for (i = 0; i < cpuid->nent; i++) {
if (cpuid->entries[i].function == HV_CPUID_ENLIGHTMENT_INFO) {
cpuid->entries[i].eax |= HV_ENLIGHTENED_VMCS_RECOMMENDED;
}
}
}
return cpuid;
}
@ -1201,24 +1218,6 @@ static int hyperv_expand_features(CPUState *cs)
if (!hyperv_enabled(cpu))
return 0;
if (hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS) ||
cpu->hyperv_passthrough) {
uint16_t evmcs_version;
r = kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_ENLIGHTENED_VMCS, 0,
(uintptr_t)&evmcs_version);
if (hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS) && r) {
fprintf(stderr, "Hyper-V %s is not supported by kernel\n",
kvm_hyperv_properties[HYPERV_FEAT_EVMCS].desc);
return -ENOSYS;
}
if (!r) {
cpu->hyperv_nested[0] = evmcs_version;
}
}
if (cpu->hyperv_passthrough) {
cpu->hyperv_vendor_id[0] =
hv_cpuid_get_host(cs, HV_CPUID_VENDOR_AND_MAX_FUNCTIONS, R_EBX);
@ -1456,6 +1455,21 @@ static int hyperv_init_vcpu(X86CPU *cpu)
}
}
if (hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS)) {
uint16_t evmcs_version;
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_ENLIGHTENED_VMCS, 0,
(uintptr_t)&evmcs_version);
if (ret < 0) {
fprintf(stderr, "Hyper-V %s is not supported by kernel\n",
kvm_hyperv_properties[HYPERV_FEAT_EVMCS].desc);
return ret;
}
cpu->hyperv_nested[0] = evmcs_version;
}
return 0;
}
@ -1520,6 +1534,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
}
if (hyperv_enabled(cpu)) {
r = hyperv_init_vcpu(cpu);
if (r) {
return r;
}
cpuid_i = hyperv_fill_cpuids(cs, cpuid_data.entries);
kvm_base = KVM_CPUID_SIGNATURE_NEXT;
has_msr_hv_hypercall = true;
@ -1869,11 +1888,6 @@ int kvm_arch_init_vcpu(CPUState *cs)
kvm_init_msrs(cpu);
r = hyperv_init_vcpu(cpu);
if (r) {
goto fail;
}
return 0;
fail: