Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> --- docs/system/i386/hyperv.rst | 4 ++++ linux-headers/linux/kvm.h | 3 ++- target/i386/cpu.c | 1 + target/i386/cpu.h | 1 + target/i386/kvm/kvm.c | 17 ++++++++++++++--- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/docs/system/i386/hyperv.rst b/docs/system/i386/hyperv.rst index 2505dc4c86e0..967acc6814f6 100644 --- a/docs/system/i386/hyperv.rst +++ b/docs/system/i386/hyperv.rst @@ -278,6 +278,10 @@ Supplementary features feature alters this behavior and only allows the guest to use exposed Hyper-V enlightenments. +``hv-evmcs-rev={revision}`` + When Enlightened VMCS definitinon changes, KVM increases the supported + 'revision' to make live migration to older hosts possible. Note: + ``hv-passthrough`` mode enables the latest supported revision. Useful links ------------ diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 0d05d02ee4fe..425ec0d636df 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -1097,7 +1097,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_PPC_NESTED_HV 160 #define KVM_CAP_HYPERV_SEND_IPI 161 #define KVM_CAP_COALESCED_PIO 162 -#define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163 +#define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163 /* Obsolete */ #define KVM_CAP_EXCEPTION_PAYLOAD 164 #define KVM_CAP_ARM_VM_IPA_SIZE 165 #define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166 /* Obsolete */ @@ -1150,6 +1150,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_DISABLE_QUIRKS2 213 /* #define KVM_CAP_VM_TSC_CONTROL 214 */ #define KVM_CAP_SYSTEM_EVENT_DATA 215 +#define KVM_CAP_HYPERV_ENLIGHTENED_VMCS2 220 #ifdef KVM_CAP_IRQ_ROUTING diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 6a57ef13af86..0d8b43f570f8 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -6994,6 +6994,7 @@ static Property x86_cpu_properties[] = { HYPERV_FEAT_SYNDBG, 0), DEFINE_PROP_BOOL("hv-passthrough", X86CPU, hyperv_passthrough, false), DEFINE_PROP_BOOL("hv-enforce-cpuid", X86CPU, hyperv_enforce_cpuid, false), + DEFINE_PROP_UINT32("hv-evmcs-rev", X86CPU, hyperv_evmcs_rev, 1), /* WS2008R2 identify by default */ DEFINE_PROP_UINT32("hv-version-id-build", X86CPU, hyperv_ver_id_build, diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 82004b65b944..d7a069703943 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1805,6 +1805,7 @@ struct ArchCPU { uint64_t hyperv_features; bool hyperv_passthrough; OnOffAuto hyperv_no_nonarch_cs; + uint32_t hyperv_evmcs_rev; uint32_t hyperv_vendor_id[3]; uint32_t hyperv_interface_id[4]; uint32_t hyperv_limits[3]; diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index e5331662b63b..490fa4582f8c 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -1635,9 +1635,20 @@ static int hyperv_init_vcpu(X86CPU *cpu) if (hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS)) { uint16_t evmcs_version = DEFAULT_EVMCS_VERSION; uint16_t supported_evmcs_version; - - ret = kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_ENLIGHTENED_VMCS, 0, - (uintptr_t)&supported_evmcs_version); + uint32_t evmcs_revision = + cpu->hyperv_passthrough ? UINT32_MAX : cpu->hyperv_evmcs_rev; + + if (kvm_check_extension(cs->kvm_state, + KVM_CAP_HYPERV_ENLIGHTENED_VMCS2)) { + ret = kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_ENLIGHTENED_VMCS2, 0, + evmcs_revision, + (uintptr_t)&supported_evmcs_version); + } else if (cpu->hyperv_evmcs_rev == 1) { + ret = kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_ENLIGHTENED_VMCS, 0, + (uintptr_t)&supported_evmcs_version); + } else { + ret = -ENOTSUP; + } /* * KVM is required to support EVMCS ver.1. as that's what 'hv-evmcs' -- 2.35.3