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

i386/kvm: add NoNonArchitecturalCoreSharing Hyper-V enlightenment



Hyper-V TLFS specifies this enlightenment as:
"NoNonArchitecturalCoreSharing - Indicates that a virtual processor will never
share a physical core with another virtual processor, except for virtual
processors that are reported as sibling SMT threads. This can be used as an
optimization to avoid the performance overhead of STIBP".

However, STIBP is not the only implication. It was found that Hyper-V on
KVM doesn't pass MD_CLEAR bit to its guests if it doesn't see
NoNonArchitecturalCoreSharing bit.

KVM reports NoNonArchitecturalCoreSharing in KVM_GET_SUPPORTED_HV_CPUID to
indicate that SMT on the host is impossible (not supported of forcefully
disabled).

Implement NoNonArchitecturalCoreSharing support in QEMU as tristate:
'off' - the feature is disabled (default)
'on' - the feature is enabled. This is only safe if vCPUS are properly
 pinned and correct topology is exposed. As CPU pinning is done outside
 of QEMU the enablement decision will be made on a higher level.
'auto' - copy KVM setting. As during live migration SMT settings on the
source and destination host may differ this requires us to add a migration
blocker.

Signed-off-by: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20191018163908.10246-1-vkuznets@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent f1733749
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -184,6 +184,19 @@ enabled.

Requires: hv-vpindex, hv-synic, hv-time, hv-stimer

3.17. hv-no-nonarch-coresharing=on/off/auto
===========================================
This enlightenment tells guest OS that virtual processors will never share a
physical core unless they are reported as sibling SMT threads. This information
is required by Windows and Hyper-V guests to properly mitigate SMT related CPU
vulnerabilities.
When the option is set to 'auto' QEMU will enable the feature only when KVM
reports that non-architectural coresharing is impossible, this means that
hyper-threading is not supported or completely disabled on the host. This
setting also prevents migration as SMT settings on the destination may differ.
When the option is set to 'on' QEMU will always enable the feature, regardless
of host setup. To keep guests secure, this can only be used in conjunction with
exposing correct vCPU topology and vCPU pinning.

4. Development features
========================
+2 −0
Original line number Diff line number Diff line
@@ -6174,6 +6174,8 @@ static Property x86_cpu_properties[] = {
                      HYPERV_FEAT_IPI, 0),
    DEFINE_PROP_BIT64("hv-stimer-direct", X86CPU, hyperv_features,
                      HYPERV_FEAT_STIMER_DIRECT, 0),
    DEFINE_PROP_ON_OFF_AUTO("hv-no-nonarch-coresharing", X86CPU,
                            hyperv_no_nonarch_cs, ON_OFF_AUTO_OFF),
    DEFINE_PROP_BOOL("hv-passthrough", X86CPU, hyperv_passthrough, false),

    DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
+2 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "cpu-qom.h"
#include "hyperv-proto.h"
#include "exec/cpu-defs.h"
#include "qapi/qapi-types-common.h"

/* The x86 has a strong memory model with some store-after-load re-ordering */
#define TCG_GUEST_DEFAULT_MO      (TCG_MO_ALL & ~TCG_MO_ST_LD)
@@ -1614,6 +1615,7 @@ struct X86CPU {
    bool hyperv_synic_kvm_only;
    uint64_t hyperv_features;
    bool hyperv_passthrough;
    OnOffAuto hyperv_no_nonarch_cs;

    bool check_cpuid;
    bool enforce_cpuid;
+1 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@
#define HV_CLUSTER_IPI_RECOMMENDED          (1u << 10)
#define HV_EX_PROCESSOR_MASKS_RECOMMENDED   (1u << 11)
#define HV_ENLIGHTENED_VMCS_RECOMMENDED     (1u << 14)
#define HV_NO_NONARCH_CORESHARING           (1u << 18)

/*
 * Basic virtualized MSRs
+26 −0
Original line number Diff line number Diff line
@@ -1227,6 +1227,16 @@ static int hyperv_handle_properties(CPUState *cs,
        }
    }

    if (cpu->hyperv_no_nonarch_cs == ON_OFF_AUTO_ON) {
        env->features[FEAT_HV_RECOMM_EAX] |= HV_NO_NONARCH_CORESHARING;
    } else if (cpu->hyperv_no_nonarch_cs == ON_OFF_AUTO_AUTO) {
        c = cpuid_find_entry(cpuid, HV_CPUID_ENLIGHTMENT_INFO, 0);
        if (c) {
            env->features[FEAT_HV_RECOMM_EAX] |=
                c->eax & HV_NO_NONARCH_CORESHARING;
        }
    }

    /* Features */
    r = hv_cpuid_check_and_set(cs, cpuid, HYPERV_FEAT_RELAXED);
    r |= hv_cpuid_check_and_set(cs, cpuid, HYPERV_FEAT_VAPIC);
@@ -1340,6 +1350,7 @@ free:
}

static Error *hv_passthrough_mig_blocker;
static Error *hv_no_nonarch_cs_mig_blocker;

static int hyperv_init_vcpu(X86CPU *cpu)
{
@@ -1359,6 +1370,21 @@ static int hyperv_init_vcpu(X86CPU *cpu)
        }
    }

    if (cpu->hyperv_no_nonarch_cs == ON_OFF_AUTO_AUTO &&
        hv_no_nonarch_cs_mig_blocker == NULL) {
        error_setg(&hv_no_nonarch_cs_mig_blocker,
                   "'hv-no-nonarch-coresharing=auto' CPU flag prevents migration"
                   " use explicit 'hv-no-nonarch-coresharing=on' instead (but"
                   " make sure SMT is disabled and/or that vCPUs are properly"
                   " pinned)");
        ret = migrate_add_blocker(hv_no_nonarch_cs_mig_blocker, &local_err);
        if (local_err) {
            error_report_err(local_err);
            error_free(hv_no_nonarch_cs_mig_blocker);
            return ret;
        }
    }

    if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) && !hv_vpindex_settable) {
        /*
         * the kernel doesn't support setting vp_index; assert that its value