Commit e204ac61 authored by Vitaly Kuznetsov's avatar Vitaly Kuznetsov Committed by Paolo Bonzini
Browse files

x86: hv_evmcs CPU flag support



Adds a new CPU flag to enable the Enlightened VMCS KVM feature.
QEMU enables KVM_CAP_HYPERV_ENLIGHTENED_VMCS and gets back the
version to be advertised in lower 16 bits of CPUID.0x4000000A:EAX.

Suggested-by: default avatarLadi Prosek <lprosek@redhat.com>
Signed-off-by: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20181022165506.30332-3-vkuznets@redhat.com>
Reviewed-by: default avatarRoman Kagan <rkagan@virtuozzo.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 013aabdc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5732,6 +5732,7 @@ static Property x86_cpu_properties[] = {
    DEFINE_PROP_BOOL("hv-frequencies", X86CPU, hyperv_frequencies, false),
    DEFINE_PROP_BOOL("hv-reenlightenment", X86CPU, hyperv_reenlightenment, false),
    DEFINE_PROP_BOOL("hv-tlbflush", X86CPU, hyperv_tlbflush, false),
    DEFINE_PROP_BOOL("hv-evmcs", X86CPU, hyperv_evmcs, false),
    DEFINE_PROP_BOOL("hv-ipi", X86CPU, hyperv_ipi, false),
    DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
    DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
+1 −0
Original line number Diff line number Diff line
@@ -1391,6 +1391,7 @@ struct X86CPU {
    bool hyperv_frequencies;
    bool hyperv_reenlightenment;
    bool hyperv_tlbflush;
    bool hyperv_evmcs;
    bool hyperv_ipi;
    bool check_cpuid;
    bool enforce_cpuid;
+2 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define HV_CPUID_FEATURES                     0x40000003
#define HV_CPUID_ENLIGHTMENT_INFO             0x40000004
#define HV_CPUID_IMPLEMENT_LIMITS             0x40000005
#define HV_CPUID_NESTED_FEATURES              0x4000000A
#define HV_CPUID_MIN                          0x40000005
#define HV_CPUID_MAX                          0x4000ffff
#define HV_HYPERVISOR_PRESENT_BIT             0x80000000
@@ -60,6 +61,7 @@
#define HV_RELAXED_TIMING_RECOMMENDED       (1u << 5)
#define HV_CLUSTER_IPI_RECOMMENDED          (1u << 10)
#define HV_EX_PROCESSOR_MASKS_RECOMMENDED   (1u << 11)
#define HV_ENLIGHTENED_VMCS_RECOMMENDED     (1u << 14)

/*
 * Basic virtualized MSRs
+28 −2
Original line number Diff line number Diff line
@@ -869,6 +869,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
    uint32_t unused;
    struct kvm_cpuid_entry2 *c;
    uint32_t signature[3];
    uint16_t evmcs_version;
    int kvm_base = KVM_CPUID_SIGNATURE;
    int r;
    Error *local_err = NULL;
@@ -912,7 +913,8 @@ int kvm_arch_init_vcpu(CPUState *cs)
            memset(signature, 0, 12);
            memcpy(signature, cpu->hyperv_vendor_id, len);
        }
        c->eax = HV_CPUID_MIN;
        c->eax = cpu->hyperv_evmcs ?
            HV_CPUID_NESTED_FEATURES : HV_CPUID_IMPLEMENT_LIMITS;
        c->ebx = signature[0];
        c->ecx = signature[1];
        c->edx = signature[2];
@@ -970,7 +972,16 @@ int kvm_arch_init_vcpu(CPUState *cs)
            c->eax |= HV_CLUSTER_IPI_RECOMMENDED;
            c->eax |= HV_EX_PROCESSOR_MASKS_RECOMMENDED;
        }

        if (cpu->hyperv_evmcs) {
            if (kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_ENLIGHTENED_VMCS, 0,
                                    (uintptr_t)&evmcs_version)) {
                fprintf(stderr, "Hyper-V Enlightened VMCS "
                        "(requested by 'hv-evmcs' cpu flag) "
                        "is not supported by kernel\n");
                return -ENOSYS;
            }
            c->eax |= HV_ENLIGHTENED_VMCS_RECOMMENDED;
        }
        c->ebx = cpu->hyperv_spinlock_attempts;

        c = &cpuid_data.entries[cpuid_i++];
@@ -981,6 +992,21 @@ int kvm_arch_init_vcpu(CPUState *cs)

        kvm_base = KVM_CPUID_SIGNATURE_NEXT;
        has_msr_hv_hypercall = true;

        if (cpu->hyperv_evmcs) {
            __u32 function;

            /* Create zeroed 0x40000006..0x40000009 leaves */
            for (function = HV_CPUID_IMPLEMENT_LIMITS + 1;
                 function < HV_CPUID_NESTED_FEATURES; function++) {
                c = &cpuid_data.entries[cpuid_i++];
                c->function = function;
            }

            c = &cpuid_data.entries[cpuid_i++];
            c->function = HV_CPUID_NESTED_FEATURES;
            c->eax = evmcs_version;
        }
    }

    if (cpu->expose_kvm) {