From nobody Sun Sep 28 00:36:28 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1561082874; cv=none; d=zoho.com; s=zohoarc; b=DpKH9rbaLyA1Rhcortk1ch8dsUpRRHlOtYNUDxGsWFiggb8Dc0ZRNi/Hwzc72j2KRKpf99/S7FyeV6yUgqrY8Zs9afM8EJxXZZ8hjnpV4nv0MlR3FiHISAWeIUpAzvmE4OLF5qkwMZjqMIQ28wyEKnCvQy/1dNJmmh4yRtc3pss= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1561082874; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=rLWxEjPZN+ttDy6470/jW3LY13Gz8VOEZike0sn0oXQ=; b=HruLLHaZEsb+Sh4aiL53poOH7g+65F3LDOmmxrW7Toa2nco5tnXVSkGZZ1RAi8rQRTyHOnKv1kzPbOR5rbBPyStjwPMTj6lNUHWI1oiJeySIVGP5NokflWSnHT6bn4QBf4umUxmk3Um/OMSCa/qlVqXUldLttax57aDsEuhnljA= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1561082874260388.3533066255444; Thu, 20 Jun 2019 19:07:54 -0700 (PDT) Received: from localhost ([::1]:54128 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1he8xz-0005yw-8h for importer@patchew.org; Thu, 20 Jun 2019 22:07:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41383) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1he8a7-0006i9-Vj for qemu-devel@nongnu.org; Thu, 20 Jun 2019 21:43:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1he8a4-0006hZ-5n for qemu-devel@nongnu.org; Thu, 20 Jun 2019 21:43:11 -0400 Received: from mail-wm1-x32e.google.com ([2a00:1450:4864:20::32e]:35230) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1he8a3-0006H9-66 for qemu-devel@nongnu.org; Thu, 20 Jun 2019 21:43:07 -0400 Received: by mail-wm1-x32e.google.com with SMTP id c6so4929085wml.0 for ; Thu, 20 Jun 2019 18:42:41 -0700 (PDT) Received: from 640k.lan ([93.56.166.5]) by smtp.gmail.com with ESMTPSA id d1sm1123125wru.41.2019.06.20.18.42.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 20 Jun 2019 18:42:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=rLWxEjPZN+ttDy6470/jW3LY13Gz8VOEZike0sn0oXQ=; b=TZZHIvtLm+DkuRRO2AQJKzG01U+Je1wC8UwFdiM+DaXQr1qnIwzu3xBJy93qXwlY1o WyboqPgRUgr1qIIKQdP4XDR/t88qM8h95n+DbSvOYDwIIJKmwrLFzIMnoOyJLgzi5/a5 HYuhiVTbXJW7cubRQFNsCK7uGU160ALpKOSNKJvNEmXNLobSxK2omSufOnMEo7jVVqo9 5s7J+TeEQPAU2SNQMlxSR5EmTgW2tTB/is2vX6d2Cx/O8gnHD4eLAXqQi+U6UflyKzN9 pLmSAalAvMtzvrJQkt4BqWIpAlYr/GE0B+J3gDxQSFz2z4gChiWlWu7brhoueuQApyoT mi8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=rLWxEjPZN+ttDy6470/jW3LY13Gz8VOEZike0sn0oXQ=; b=G0Zh7t/MTQFQFoOrGVk1dVyYHuEg35699z0oS7UB0AHYRIjd1/F4DPr093CUCTFzvb O0uHochhXujQKQe2I4yBOvWNguP4Cj0jM51xIbDlVq3dEGsbbl7lrGNE5zSnNz5LDlJf cghuVc2SKIjl+RDHgD1SC6vHDQN90e8NqaTxca7F77T60m/OISmVi1hzBaSyG3nAHKBG EHK2GlmbjbLy+Yeme2k5zwitnhPPOflkeLNFUI1ZBm9DEmA7iuv/hbcY8wvNa9vNZJAk Ra8YXjPzNSd+nD1jr8HGKd905wUOzbx/xebAzpV9Eks32/tTWCkD/dZAgqPDfTpAxlwx PySg== X-Gm-Message-State: APjAAAX8gIQqVtE77woBHapK4IeMj8PXD13L6sG7NlAxT1Wg5VVRHuk1 GpG1soM3Q6gSr2A0WfspjYbnhbPG X-Google-Smtp-Source: APXvYqwAUnczJwFYtM12p0LE6xdnzBvr+y1QVlH8VScxu4voXqZljbwu+u9naqQDgylmEkNib9QHDA== X-Received: by 2002:a05:600c:2243:: with SMTP id a3mr1459914wmm.83.1561081360686; Thu, 20 Jun 2019 18:42:40 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Fri, 21 Jun 2019 03:42:12 +0200 Message-Id: <1561081350-3723-8-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1561081350-3723-1-git-send-email-pbonzini@redhat.com> References: <1561081350-3723-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::32e Subject: [Qemu-devel] [PULL 07/25] i386/kvm: implement 'hv-passthrough' mode X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Vitaly Kuznetsov Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Vitaly Kuznetsov In many case we just want to give Windows guests all currently supported Hyper-V enlightenments and that's where this new mode may come handy. We pass through what was returned by KVM_GET_SUPPORTED_HV_CPUID. hv_cpuid_check_and_set() is modified to also set cpu->hyperv_* flags as we may want to check them later (and we actually do for hv_runtime, hv_synic,...). 'hv-passthrough' is a development only feature, a migration blocker is added to prevent issues while migrating between hosts with different feature sets. Signed-off-by: Vitaly Kuznetsov Message-Id: <20190517141924.19024-6-vkuznets@redhat.com> Signed-off-by: Paolo Bonzini --- docs/hyperv.txt | 10 +++++++ target/i386/cpu.c | 1 + target/i386/cpu.h | 1 + target/i386/kvm.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++-----= ---- 4 files changed, 87 insertions(+), 14 deletions(-) diff --git a/docs/hyperv.txt b/docs/hyperv.txt index c423e0f..beadb2d 100644 --- a/docs/hyperv.txt +++ b/docs/hyperv.txt @@ -175,6 +175,16 @@ without the feature to find out if enabling it is bene= ficial. Requires: hv-vapic =20 =20 +4. Development features +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +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 featu= res +may differ between target and destination. + + 4. Useful links =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Hyper-V Top Level Functional specification and other information: diff --git a/target/i386/cpu.c b/target/i386/cpu.c index e90c1ac..e07996c 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -5883,6 +5883,7 @@ static Property x86_cpu_properties[] =3D { HYPERV_FEAT_EVMCS, 0), DEFINE_PROP_BIT64("hv-ipi", X86CPU, hyperv_features, HYPERV_FEAT_IPI, 0), + DEFINE_PROP_BOOL("hv-passthrough", X86CPU, hyperv_passthrough, false), =20 DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true), DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false), diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 30cd1a0..86edbf5 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1390,6 +1390,7 @@ struct X86CPU { char *hyperv_vendor_id; bool hyperv_synic_kvm_only; uint64_t hyperv_features; + bool hyperv_passthrough; =20 bool check_cpuid; bool enforce_cpuid; diff --git a/target/i386/kvm.c b/target/i386/kvm.c index a041b4d..93ac6ba 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -639,7 +639,7 @@ static bool hyperv_enabled(X86CPU *cpu) CPUState *cs =3D CPU(cpu); return kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV) > 0 && ((cpu->hyperv_spinlock_attempts !=3D HYPERV_SPINLOCK_NEVER_RETRY) = || - cpu->hyperv_features); + cpu->hyperv_features || cpu->hyperv_passthrough); } =20 static int kvm_arch_set_tsc_khz(CPUState *cs) @@ -985,10 +985,10 @@ static int hv_cpuid_check_and_set(CPUState *cs, struc= t kvm_cpuid2 *cpuid, { X86CPU *cpu =3D X86_CPU(cs); CPUX86State *env =3D &cpu->env; - uint32_t r, fw, bits;; + uint32_t r, fw, bits; int i; =20 - if (!hyperv_feat_enabled(cpu, feature)) { + if (!hyperv_feat_enabled(cpu, feature) && !cpu->hyperv_passthrough) { return 0; } =20 @@ -1001,15 +1001,23 @@ static int hv_cpuid_check_and_set(CPUState *cs, str= uct kvm_cpuid2 *cpuid, } =20 if (hv_cpuid_get_fw(cpuid, fw, &r) || (r & bits) !=3D bits) { - fprintf(stderr, - "Hyper-V %s is not supported by kernel\n", - kvm_hyperv_properties[feature].desc); - return 1; + if (hyperv_feat_enabled(cpu, feature)) { + fprintf(stderr, + "Hyper-V %s is not supported by kernel\n", + kvm_hyperv_properties[feature].desc); + return 1; + } else { + return 0; + } } =20 env->features[fw] |=3D bits; } =20 + if (cpu->hyperv_passthrough) { + cpu->hyperv_features |=3D BIT(feature); + } + return 0; } =20 @@ -1027,22 +1035,29 @@ static int hyperv_handle_properties(CPUState *cs, struct kvm_cpuid_entry2 *c; uint32_t signature[3]; uint32_t cpuid_i =3D 0; - int r =3D 0; + int r; =20 if (!hyperv_enabled(cpu)) return 0; =20 - if (hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS)) { + if (hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS) || + cpu->hyperv_passthrough) { uint16_t evmcs_version; =20 - if (kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_ENLIGHTENED_VMCS, 0, - (uintptr_t)&evmcs_version)) { + r =3D 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; } - env->features[FEAT_HV_RECOMM_EAX] |=3D HV_ENLIGHTENED_VMCS_RECOMME= NDED; - env->features[FEAT_HV_NESTED_EAX] =3D evmcs_version; + + if (!r) { + env->features[FEAT_HV_RECOMM_EAX] |=3D + HV_ENLIGHTENED_VMCS_RECOMMENDED; + env->features[FEAT_HV_NESTED_EAX] =3D evmcs_version; + } } =20 if (kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV_CPUID) > 0) { @@ -1051,8 +1066,33 @@ static int hyperv_handle_properties(CPUState *cs, cpuid =3D get_supported_hv_cpuid_legacy(cs); } =20 + if (cpu->hyperv_passthrough) { + memcpy(cpuid_ent, &cpuid->entries[0], + cpuid->nent * sizeof(cpuid->entries[0])); + + c =3D cpuid_find_entry(cpuid, HV_CPUID_FEATURES, 0); + if (c) { + env->features[FEAT_HYPERV_EAX] =3D c->eax; + env->features[FEAT_HYPERV_EBX] =3D c->ebx; + env->features[FEAT_HYPERV_EDX] =3D c->eax; + } + c =3D cpuid_find_entry(cpuid, HV_CPUID_ENLIGHTMENT_INFO, 0); + if (c) { + env->features[FEAT_HV_RECOMM_EAX] =3D c->eax; + + /* hv-spinlocks may have been overriden */ + if (cpu->hyperv_spinlock_attempts !=3D HYPERV_SPINLOCK_NEVER_R= ETRY) { + c->ebx =3D cpu->hyperv_spinlock_attempts; + } + } + c =3D cpuid_find_entry(cpuid, HV_CPUID_NESTED_FEATURES, 0); + if (c) { + env->features[FEAT_HV_NESTED_EAX] =3D c->eax; + } + } + /* Features */ - r |=3D hv_cpuid_check_and_set(cs, cpuid, HYPERV_FEAT_RELAXED); + r =3D hv_cpuid_check_and_set(cs, cpuid, HYPERV_FEAT_RELAXED); r |=3D hv_cpuid_check_and_set(cs, cpuid, HYPERV_FEAT_VAPIC); r |=3D hv_cpuid_check_and_set(cs, cpuid, HYPERV_FEAT_TIME); r |=3D hv_cpuid_check_and_set(cs, cpuid, HYPERV_FEAT_CRASH); @@ -1085,6 +1125,12 @@ static int hyperv_handle_properties(CPUState *cs, goto free; } =20 + if (cpu->hyperv_passthrough) { + /* We already copied all feature words from KVM as is */ + r =3D cpuid->nent; + goto free; + } + c =3D &cpuid_ent[cpuid_i++]; c->function =3D HV_CPUID_VENDOR_AND_MAX_FUNCTIONS; if (!cpu->hyperv_vendor_id) { @@ -1156,11 +1202,26 @@ free: return r; } =20 +static Error *hv_passthrough_mig_blocker; + static int hyperv_init_vcpu(X86CPU *cpu) { CPUState *cs =3D CPU(cpu); + Error *local_err =3D NULL; int ret; =20 + if (cpu->hyperv_passthrough && hv_passthrough_mig_blocker =3D=3D NULL)= { + error_setg(&hv_passthrough_mig_blocker, + "'hv-passthrough' CPU flag prevents migration, use expl= icit" + " set of hv-* flags instead"); + ret =3D migrate_add_blocker(hv_passthrough_mig_blocker, &local_err= ); + if (local_err) { + error_report_err(local_err); + error_free(hv_passthrough_mig_blocker); + return ret; + } + } + if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) && !hv_vpindex_setta= ble) { /* * the kernel doesn't support setting vp_index; assert that its va= lue --=20 1.8.3.1