From 00c1b316edb33f2efb0775c2983bc5348c86529d Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 8 Jun 2021 14:08:10 +0200 Subject: i386: clarify 'hv-passthrough' behavior Clarify the fact that 'hv-passthrough' only enables features which are already known to QEMU and that it overrides all other 'hv-*' settings. Reviewed-by: Eduardo Habkost Signed-off-by: Vitaly Kuznetsov Message-Id: <20210608120817.1325125-3-vkuznets@redhat.com> Signed-off-by: Eduardo Habkost --- docs/hyperv.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/hyperv.txt b/docs/hyperv.txt index e53c581f45..a51953daa8 100644 --- a/docs/hyperv.txt +++ b/docs/hyperv.txt @@ -209,8 +209,11 @@ In some cases (e.g. during development) it may make sense to use QEMU in 'pass-through' mode and give Windows guests all enlightenments currently supported by KVM. This pass-through mode is enabled by "hv-passthrough" CPU flag. -Note: enabling this flag effectively prevents migration as supported features -may differ between target and destination. +Note: "hv-passthrough" flag only enables enlightenments which are known to QEMU +(have corresponding "hv-*" flag) and copies "hv-spinlocks="/"hv-vendor-id=" +values from KVM to QEMU. "hv-passthrough" overrides all other "hv-*" settings on +the command line. Also, enabling this flag effectively prevents migration as the +list of enabled enlightenments may differ between target and destination hosts. 4. Useful links -- cgit v1.2.3-55-g7522 From 07454e2ea84ee9be298c96d9730dc82abfb1488a Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 8 Jun 2021 14:08:11 +0200 Subject: i386: hardcode supported eVMCS version to '1' Currently, the only eVMCS version, supported by KVM (and described in TLFS) is '1'. When Enlightened VMCS feature is enabled, QEMU takes the supported eVMCS version range (from KVM_CAP_HYPERV_ENLIGHTENED_VMCS enablement) and puts it to guest visible CPUIDs. When (and if) eVMCS ver.2 appears a problem on migration is expected: it doesn't seem to be possible to migrate from a host supporting eVMCS ver.2 to a host, which only support eVMCS ver.1. Hardcode eVMCS ver.1 as the result of 'hv-evmcs' enablement for now. Newer eVMCS versions will have to have their own enablement options (e.g. 'hv-evmcs=2'). Signed-off-by: Vitaly Kuznetsov Reviewed-by: Eduardo Habkost Message-Id: <20210608120817.1325125-4-vkuznets@redhat.com> Signed-off-by: Eduardo Habkost --- docs/hyperv.txt | 2 +- target/i386/kvm/kvm.c | 39 +++++++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/docs/hyperv.txt b/docs/hyperv.txt index a51953daa8..000638a2fd 100644 --- a/docs/hyperv.txt +++ b/docs/hyperv.txt @@ -170,7 +170,7 @@ Recommended: hv-frequencies 3.16. hv-evmcs =============== The enlightenment is nested specific, it targets Hyper-V on KVM guests. When -enabled, it provides Enlightened VMCS feature to the guest. The feature +enabled, it provides Enlightened VMCS version 1 feature to the guest. The feature implements paravirtualized protocol between L0 (KVM) and L1 (Hyper-V) hypervisors making L2 exits to the hypervisor faster. The feature is Intel-only. Note: some virtualization features (e.g. Posted Interrupts) are disabled when diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index a85035492f..02216b7031 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -1409,6 +1409,21 @@ static int hyperv_fill_cpuids(CPUState *cs, static Error *hv_passthrough_mig_blocker; static Error *hv_no_nonarch_cs_mig_blocker; +/* Checks that the exposed eVMCS version range is supported by KVM */ +static bool evmcs_version_supported(uint16_t evmcs_version, + uint16_t supported_evmcs_version) +{ + uint8_t min_version = evmcs_version & 0xff; + uint8_t max_version = evmcs_version >> 8; + uint8_t min_supported_version = supported_evmcs_version & 0xff; + uint8_t max_supported_version = supported_evmcs_version >> 8; + + return (min_version >= min_supported_version) && + (max_version <= max_supported_version); +} + +#define DEFAULT_EVMCS_VERSION ((1 << 8) | 1) + static int hyperv_init_vcpu(X86CPU *cpu) { CPUState *cs = CPU(cpu); @@ -1488,17 +1503,33 @@ static int hyperv_init_vcpu(X86CPU *cpu) } if (hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS)) { - uint16_t evmcs_version; + 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)&evmcs_version); + (uintptr_t)&supported_evmcs_version); + /* + * KVM is required to support EVMCS ver.1. as that's what 'hv-evmcs' + * option sets. Note: we hardcode the maximum supported eVMCS version + * to '1' as well so 'hv-evmcs' feature is migratable even when (and if) + * ver.2 is implemented. A new option (e.g. 'hv-evmcs=2') will then have + * to be added. + */ if (ret < 0) { - fprintf(stderr, "Hyper-V %s is not supported by kernel\n", - kvm_hyperv_properties[HYPERV_FEAT_EVMCS].desc); + error_report("Hyper-V %s is not supported by kernel", + kvm_hyperv_properties[HYPERV_FEAT_EVMCS].desc); return ret; } + if (!evmcs_version_supported(evmcs_version, supported_evmcs_version)) { + error_report("eVMCS version range [%d..%d] is not supported by " + "kernel (supported: [%d..%d])", evmcs_version & 0xff, + evmcs_version >> 8, supported_evmcs_version & 0xff, + supported_evmcs_version >> 8); + return -ENOTSUP; + } + cpu->hyperv_nested[0] = evmcs_version; } -- cgit v1.2.3-55-g7522