From nobody Tue Feb 10 06:25:02 2026 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=1562080369; cv=none; d=zoho.com; s=zohoarc; b=XPerEcWZEiwjqVeoCJt8PxAm/ce/IZCvONsYzI/jvARc49Rw1wOCfNqLehArx2b4gx/SK4iWeRgt1nxGaIuVa6GPkbWw+chPitpu28Gcc1SZqA3SYBZwUuH7OYlBiHrfMjcZf7zYQabGeqIGJ4ElxbQ15nh1Vdg5ygqfgTG7cYM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1562080369; 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=Hr3iA7qAJtOCS8u1vEWGuD19D8NaEBdGyux4f0bmqyI=; b=h6YzEvY194w5DsgFRwlpY7qXjRcVM4Om65PeYJytPr8mQ7Scavs3F3IzydGc9IYy1i7CKG4gbJC9rrr7zEQ68B62ZQgAsVTIXfPpbXth3EyikkR47SdYkh1rFR/AzyRbLxyrO3utpXajWyBWOWPmTa/jeMs7A46E5xGR9krEzmg= 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 (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1562080369989772.3557082229476; Tue, 2 Jul 2019 08:12:49 -0700 (PDT) Received: from localhost ([::1]:54362 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hiKSX-0002Ql-IC for importer@patchew.org; Tue, 02 Jul 2019 11:12:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57044) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hiKIC-0001iU-BH for qemu-devel@nongnu.org; Tue, 02 Jul 2019 11:02:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hiKI9-0004jl-OD for qemu-devel@nongnu.org; Tue, 02 Jul 2019 11:02:00 -0400 Received: from mail-wm1-x342.google.com ([2a00:1450:4864:20::342]:52212) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hiKI8-0004T2-0e for qemu-devel@nongnu.org; Tue, 02 Jul 2019 11:01:57 -0400 Received: by mail-wm1-x342.google.com with SMTP id 207so1187580wma.1 for ; Tue, 02 Jul 2019 08:01:32 -0700 (PDT) Received: from 640k.lan ([93.56.166.5]) by smtp.gmail.com with ESMTPSA id m24sm3006262wmi.39.2019.07.02.08.01.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 02 Jul 2019 08:01:30 -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=Hr3iA7qAJtOCS8u1vEWGuD19D8NaEBdGyux4f0bmqyI=; b=l42jDHFwQe1K86tprB9SlNbdem8F6Y5pZM9QCWnDoVx4wqanpO/0R2EBTBh26T45uW Eu3sJvS97jMGNyIgGKFX+DroPiGeUY3tTFJR2S3JTotsye7xe2R4k+gzqYsIrUSnVy1h dpELEm6frtD1AJmYDP/9JMlv/1PEfauRIrfxAQpItlEztjA8/WeMFQEV6CaH1GUVWAly oZRG+8o7Qr96+QFAnh57MHEKUsckvaYmsRDacv5UvNE7h2RVLwS/KAPxRyocf8D0r4ZL AL8UW2U5FQNP6ulXF/jfzp8gOtS5Vo1Fir/+tFFIVlLpvo3E7FZU28sFepM7dKXGg+pL eMEw== 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=Hr3iA7qAJtOCS8u1vEWGuD19D8NaEBdGyux4f0bmqyI=; b=gveo4wyKxPW163zg+9QohfZytmNN0tm3yW6npSfC6qGuTZMDs+bMFiTPxKfOh6h1eB vz1X+ZjHxsCATWC3l2/uTvrG7jkcAtVD+bUuxdbChLEvi3zGQcsgYpNroMLxF6KnctG6 2Ic/xp4eM4VvY7s/qFYP/ewU84KrL+F4iolFyeL8/zeCt8WnhzOaUD+CaV0R9gP0jDSi DLVwDLS/dZpUXLgPdf3Nk0EV92RvuUUkJR6FWu8m0zQnyTqslVnY9C3CRy/OKPeVxnjC TdIGcCfBKdkwWQNYR4Y0q5wtul2gRmWBQjOy2n2RKyeHa+bjwtLmbWxUQLa6MVWs67jt TS4g== X-Gm-Message-State: APjAAAWWfWKrgmS+Uh01i4IgPi3FMuLT/F3dcxv62upFVLBpNq1iMCYp J994IsGBLAwKeCYBEPWe9wYQVwoF4dk= X-Google-Smtp-Source: APXvYqzCFuj4E2KA51xgIn5v/BU53alrRHAYCMVqEko6mcnvhWixgVwEKhDK58+xFbi+rkv5zIq8IQ== X-Received: by 2002:a7b:c455:: with SMTP id l21mr3855243wmi.114.1562079691234; Tue, 02 Jul 2019 08:01:31 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 2 Jul 2019 17:01:20 +0200 Message-Id: <1562079681-19204-7-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1562079681-19204-1-git-send-email-pbonzini@redhat.com> References: <1562079681-19204-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::342 Subject: [Qemu-devel] [PATCH 6/7] target/i386: add VMX features 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: Liran Alon , Eduardo Habkost 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" Add code to convert the VMX feature words back into MSR values, allowing the user to enable/disable VMX features as they wish. The same infrastructure enables support for limiting VMX features in named CPU models. Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ target/i386/cpu.h | 9 +++ target/i386/kvm.c | 154 ++++++++++++++++++++++++++++++++++++- 3 files changed, 382 insertions(+), 2 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 4de44e4..12f76a3 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1211,6 +1211,163 @@ static FeatureWordInfo feature_word_info[FEATURE_WO= RDS] =3D { .index =3D MSR_IA32_CORE_CAPABILITY, }, }, + + [FEAT_VMX_PROCBASED_CTLS] =3D { + .type =3D MSR_FEATURE_WORD, + .feat_names =3D { + NULL, NULL, "vmx-vintr-pending", "vmx-tsc-offset", + NULL, NULL, NULL, "vmx-hlt-exit", + NULL, "vmx-invlpg-exit", "vmx-mwait-exit", "vmx-rdpmc-exit", + "vmx-rdtsc-exit", NULL, NULL, "vmx-cr3-load-noexit", + "vmx-cr3-store-noexit", NULL, NULL, "vmx-cr8-load-exit", + "vmx-cr8-store-exit", "vmx-flexpriority", "vmx-vnmi-pending", = "vmx-movdr-exit", + "vmx-io-exit", "vmx-io-bitmap", NULL, "vmx-mtf", + "vmx-msr-bitmap", "vmx-monitor-exit", "vmx-pause-exit", "vmx-s= econdary-ctls", + }, + .msr =3D { + .index =3D MSR_IA32_VMX_TRUE_PROCBASED_CTLS, + } + }, + + [FEAT_VMX_SECONDARY_CTLS] =3D { + .type =3D MSR_FEATURE_WORD, + .feat_names =3D { + "vmx-apicv-xapic", "vmx-ept", "vmx-desc-exit", "vmx-rdtscp-exi= t", + "vmx-apicv-x2apic", "vmx-vpid", "vmx-wbinvd-exit", "vmx-unrest= ricted-guest", + "vmx-apicv-register", "vmx-apicv-vid", "vmx-ple", "vmx-rdrand-= exit", + "vmx-invpcid-exit", "vmx-vmfunc", "vmx-shadow-vmcs", "vmx-encl= s-exit", + "vmx-rdseed-exit", "vmx-pml", NULL, NULL, + "vmx-xsaves", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, + .msr =3D { + .index =3D MSR_IA32_VMX_PROCBASED_CTLS2, + } + }, + + [FEAT_VMX_PINBASED_CTLS] =3D { + .type =3D MSR_FEATURE_WORD, + .feat_names =3D { + "vmx-intr-exit", NULL, NULL, "vmx-nmi-exit", + NULL, "vmx-vnmi", "vmx-preemption-timer", "vmx-posted-intr", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, + .msr =3D { + .index =3D MSR_IA32_VMX_TRUE_PINBASED_CTLS, + } + }, + + [FEAT_VMX_EXIT_CTLS] =3D { + .type =3D MSR_FEATURE_WORD, + /* + * VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE is copied from + * the LM CPUID bit. + */ + .feat_names =3D { + NULL, NULL, "vmx-exit-nosave-debugctl", NULL, + NULL, NULL, NULL, NULL, + NULL, NULL /* vmx-exit-host-addr-space-size */, NULL, NULL, + "vmx-exit-load-perf-global-ctrl", NULL, NULL, "vmx-exit-ack-in= tr", + NULL, NULL, "vmx-exit-save-pat", "vmx-exit-load-pat", + "vmx-exit-save-efer", "vmx-exit-load-efer", + "vmx-exit-save-preemption-timer", "vmx-exit-clear-bndcfgs", + NULL, "vmx-exit-clear-rtit-ctl", NULL, NULL, + NULL, NULL, NULL, NULL, + }, + .msr =3D { + .index =3D MSR_IA32_VMX_TRUE_EXIT_CTLS, + } + }, + + [FEAT_VMX_ENTRY_CTLS] =3D { + .type =3D MSR_FEATURE_WORD, + .feat_names =3D { + NULL, NULL, "vmx-entry-noload-debugctl", NULL, + NULL, NULL, NULL, NULL, + NULL, "vmx-entry-ia32e-mode", NULL, NULL, + NULL, "vmx-entry-load-perf-global-ctrl", "vmx-entry-load-pat",= "vmx-entry-load-efer", + "vmx-entry-load-bndcfgs", NULL, "vmx-entry-load-rtit-ctl", NUL= L, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, + .msr =3D { + .index =3D MSR_IA32_VMX_TRUE_ENTRY_CTLS, + } + }, + + [FEAT_VMX_MISC] =3D { + .type =3D MSR_FEATURE_WORD, + .feat_names =3D { + NULL, NULL, NULL, NULL, + NULL, "vmx-store-lma", "vmx-activity-hlt", "vmx-activity-shutd= own", + "vmx-activity-wait-sipi", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, "vmx-vmwrite-vmexit-fields", "vmx-zero-len-inject", NULL, + }, + .msr =3D { + .index =3D MSR_IA32_VMX_MISC, + } + }, + + [FEAT_VMX_EPT_VPID_CAPS] =3D { + .type =3D MSR_FEATURE_WORD, + .feat_names =3D { + "vmx-ept-execonly", NULL, NULL, NULL, + NULL, NULL, "vmx-page-walk-4", "vmx-page-walk-5", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + "vmx-ept-2mb", "vmx-ept-1gb", NULL, NULL, + "vmx-invept", "vmx-eptad", "vmx-ept-advanced-exitinfo", NULL, + NULL, "vmx-invept-single-context", "vmx-invept-all-context", N= ULL, + NULL, NULL, NULL, NULL, + "vmx-invvpid", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + "vmx-invvpid-single-addr", "vmx-invept-single-context", + "vmx-invvpid-all-context", "vmx-invept-single-context-nogl= obals", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, + .msr =3D { + .index =3D MSR_IA32_VMX_EPT_VPID_CAP, + } + }, + + [FEAT_VMX_BASIC] =3D { + .type =3D MSR_FEATURE_WORD, + .feat_names =3D { + [54] =3D "vmx-ins-outs", + [55] =3D "vmx-true-ctls", + }, + .msr =3D { + .index =3D MSR_IA32_VMX_BASIC, + }, + /* Just to be safe - we don't support setting the MSEG version fie= ld. */ + .no_autoenable_flags =3D MSR_VMX_BASIC_DUAL_MONITOR, + }, + + [FEAT_VMX_VMFUNC] =3D { + .type =3D MSR_FEATURE_WORD, + .feat_names =3D { + [0] =3D "vmx-eptp-switching", + }, + .msr =3D { + .index =3D MSR_IA32_VMX_VMFUNC, + } + }, + }; =20 typedef struct FeatureDep { @@ -1227,6 +1384,70 @@ static FeatureDep feature_dependencies[] =3D { .from =3D FEAT_7_0_EDX, .from_flag =3D CPUID_7_0_EDX_CO= RE_CAPABILITY, .to =3D FEAT_CORE_CAPABILITY, .to_flags =3D ~0ull, }, + { + .from =3D FEAT_1_ECX, .from_flag =3D CPUID_EXT_VMX, + .to =3D FEAT_VMX_PROCBASED_CTLS, .to_flags =3D ~0ull, + }, + { + .from =3D FEAT_1_ECX, .from_flag =3D CPUID_EXT_VMX, + .to =3D FEAT_VMX_PINBASED_CTLS, .to_flags =3D ~0ull, + }, + { + .from =3D FEAT_1_ECX, .from_flag =3D CPUID_EXT_VMX, + .to =3D FEAT_VMX_EXIT_CTLS, .to_flags =3D ~0ull, + }, + { + .from =3D FEAT_1_ECX, .from_flag =3D CPUID_EXT_VMX, + .to =3D FEAT_VMX_ENTRY_CTLS, .to_flags =3D ~0ull, + }, + { + .from =3D FEAT_1_ECX, .from_flag =3D CPUID_EXT_VMX, + .to =3D FEAT_VMX_MISC, .to_flags =3D ~0ull, + }, + { + .from =3D FEAT_1_ECX, .from_flag =3D CPUID_EXT_VMX, + .to =3D FEAT_VMX_BASIC, .to_flags =3D ~0ull, + }, + { + .from =3D FEAT_8000_0001_EDX, .from_flag =3D CPUID_EXT2_LM, + .to =3D FEAT_VMX_ENTRY_CTLS, .to_flags =3D VMX_VM_ENTRY_IA32= E_MODE, + }, + { + .from =3D FEAT_VMX_PROCBASED_CTLS, .from_flag =3D VMX_CPU_BASED_AC= TIVATE_SECONDARY_CONTROLS, + .to =3D FEAT_VMX_SECONDARY_CTLS, .to_flags =3D ~0ull, + }, + { + .from =3D FEAT_XSAVE, .from_flag =3D CPUID_XSAVE_XSAV= ES, + .to =3D FEAT_VMX_SECONDARY_CTLS, .to_flags =3D VMX_SECONDARY_EXE= C_XSAVES, + }, + { + .from =3D FEAT_1_ECX, .from_flag =3D CPUID_EXT_RDRAND, + .to =3D FEAT_VMX_SECONDARY_CTLS, .to_flags =3D VMX_SECONDARY_EXE= C_RDRAND_EXITING, + }, + { + .from =3D FEAT_7_0_EBX, .from_flag =3D CPUID_7_0_EBX_IN= VPCID, + .to =3D FEAT_VMX_SECONDARY_CTLS, .to_flags =3D VMX_SECONDARY_EXE= C_ENABLE_INVPCID, + }, + { + .from =3D FEAT_7_0_EBX, .from_flag =3D CPUID_7_0_EBX_RD= SEED, + .to =3D FEAT_VMX_SECONDARY_CTLS, .to_flags =3D VMX_SECONDARY_EXE= C_RDSEED_EXITING, + }, + { + .from =3D FEAT_8000_0001_EDX, .from_flag =3D CPUID_EXT2_RDTSC= P, + .to =3D FEAT_VMX_SECONDARY_CTLS, .to_flags =3D VMX_SECONDARY_EXE= C_RDTSCP, + }, + { + .from =3D FEAT_VMX_SECONDARY_CTLS, .from_flag =3D VMX_SECONDARY_EX= EC_ENABLE_EPT, + .to =3D FEAT_VMX_EPT_VPID_CAPS, .to_flags =3D 0xffffffffull, + }, + { + .from =3D FEAT_VMX_SECONDARY_CTLS, .from_flag =3D VMX_SECONDARY_EX= EC_ENABLE_VPID, + .to =3D FEAT_VMX_EPT_VPID_CAPS, .to_flags =3D 0xffffffffull << = 32, + }, + { + .from =3D FEAT_VMX_SECONDARY_CTLS, .from_flag =3D VMX_SECONDARY_EX= EC_ENABLE_VMFUNC, + .to =3D FEAT_VMX_VMFUNC, .to_flags =3D ~0ull, + }, }; =20 typedef struct X86RegisterInfo32 { diff --git a/target/i386/cpu.h b/target/i386/cpu.h index ec479d5..a5710c1 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -517,6 +517,15 @@ typedef enum FeatureWord { FEAT_XSAVE_COMP_HI, /* CPUID[EAX=3D0xd,ECX=3D0].EDX */ FEAT_ARCH_CAPABILITIES, FEAT_CORE_CAPABILITY, + FEAT_VMX_PROCBASED_CTLS, + FEAT_VMX_SECONDARY_CTLS, + FEAT_VMX_PINBASED_CTLS, + FEAT_VMX_EXIT_CTLS, + FEAT_VMX_ENTRY_CTLS, + FEAT_VMX_MISC, + FEAT_VMX_EPT_VPID_CAPS, + FEAT_VMX_BASIC, + FEAT_VMX_VMFUNC, FEATURE_WORDS, } FeatureWord; =20 diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 6801696..e35489c 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -96,6 +96,7 @@ static bool has_msr_virt_ssbd; static bool has_msr_smi_count; static bool has_msr_arch_capabs; static bool has_msr_core_capabs; +static bool has_msr_vmx_vmfunc; =20 static uint32_t has_architectural_pmu_version; static uint32_t num_architectural_pmu_gp_counters; @@ -438,7 +439,8 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s= , uint32_t index) struct kvm_msrs info; struct kvm_msr_entry entries[1]; } msr_data; - uint32_t ret; + uint64_t value; + uint32_t ret, can_be_one, must_be_one; =20 if (kvm_feature_msrs =3D=3D NULL) { /* Host doesn't support feature MS= Rs */ return 0; @@ -464,7 +466,25 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *= s, uint32_t index) exit(1); } =20 - return msr_data.entries[0].data; + value =3D msr_data.entries[0].data; + switch (index) { + case MSR_IA32_VMX_PROCBASED_CTLS2: + case MSR_IA32_VMX_TRUE_PINBASED_CTLS: + case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: + case MSR_IA32_VMX_TRUE_ENTRY_CTLS: + case MSR_IA32_VMX_TRUE_EXIT_CTLS: + /* + * Return true for bits that can be one, but do not have to be one. + * The SDM tells us which bits could have a "must be one" setting, + * so we can do the opposite transformation in make_vmx_msr_value. + */ + must_be_one =3D (uint32_t)value; + can_be_one =3D (uint32_t)(value >> 32); + return can_be_one & ~must_be_one; + + default: + return value; + } } =20 =20 @@ -1933,6 +1953,9 @@ static int kvm_get_supported_msrs(KVMState *s) case MSR_IA32_CORE_CAPABILITY: has_msr_core_capabs =3D true; break; + case MSR_IA32_VMX_VMFUNC: + has_msr_vmx_vmfunc =3D true; + break; } } } @@ -2407,6 +2430,126 @@ static int kvm_put_msr_feature_control(X86CPU *cpu) return 0; } =20 +static uint64_t make_vmx_msr_value(uint32_t index, uint32_t features) +{ + uint32_t default1, can_be_one, can_be_zero; + uint32_t must_be_one; + + switch (index) { + case MSR_IA32_VMX_TRUE_PINBASED_CTLS: + default1 =3D 0x00000016; + break; + case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: + default1 =3D 0x0401e172; + break; + case MSR_IA32_VMX_TRUE_ENTRY_CTLS: + default1 =3D 0x000011ff; + break; + case MSR_IA32_VMX_TRUE_EXIT_CTLS: + default1 =3D 0x00036dff; + break; + case MSR_IA32_VMX_PROCBASED_CTLS2: + default1 =3D 0; + break; + default: + abort(); + } + + /* If a feature bit is set, the control can be either set or clear. + * Otherwise the value is limited to either 0 or 1 by default1. + */ + can_be_one =3D features | default1; + can_be_zero =3D features | ~default1; + must_be_one =3D ~can_be_zero; + + /* + * Bit 0:31 -> 0 if the control bit can be zero (i.e. 1 if it must be = one). + * Bit 32:63 -> 1 if the control bit can be one. + */ + return must_be_one | (((uint64_t)can_be_one) << 32); +} + +#define VMCS12_MAX_FIELD_INDEX (0x17) + +static void kvm_msr_entry_add_vmx(X86CPU *cpu, FeatureWordArray f) +{ + uint64_t kvm_vmx_basic =3D + kvm_arch_get_supported_msr_feature(kvm_state, + MSR_IA32_VMX_BASIC); + uint64_t kvm_vmx_misc =3D + kvm_arch_get_supported_msr_feature(kvm_state, + MSR_IA32_VMX_MISC); + uint64_t kvm_vmx_ept_vpid =3D + kvm_arch_get_supported_msr_feature(kvm_state, + MSR_IA32_VMX_EPT_VPID_CAP); + + /* + * If the guest is 64-bit, a value of 1 is allowed for the host address + * space size vmexit control. + */ + uint64_t fixed_vmx_exit =3D f[FEAT_8000_0001_EDX] & CPUID_EXT2_LM + ? (uint64_t)VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE << 32 : 0; + + /* + * Bits 0-30, 32-44 and 50-53 come from the host. KVM should + * not change them for backwards compatibility. + */ + uint64_t fixed_vmx_basic =3D kvm_vmx_basic & 0x003c1fff7fffffffULL; + + /* + * Same for bits 0-4 and 25-27. Bits 16-24 (CR3 target count) can + * change in the future but are always zero for now, clear them to be + * future proof. Bits 32-63 in theory could change, though KVM does + * not support dual-monitor treatment and probably never will; mask + * them out as well. + */ + uint64_t fixed_vmx_misc =3D kvm_vmx_misc & 0x0e00001f; + + /* + * EPT memory types should not change either, so we do not bother + * adding features for them. + */ + uint64_t fixed_vmx_ept_mask =3D + (f[FEAT_VMX_SECONDARY_CTLS] & VMX_SECONDARY_EXEC_ENABLE_EPT ? = 0x4100ull : 0); + uint64_t fixed_vmx_ept_vpid =3D kvm_vmx_ept_vpid & fixed_vmx_ept_mask; + + kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS, + make_vmx_msr_value(MSR_IA32_VMX_TRUE_PROCBASED_CTLS, + f[FEAT_VMX_PROCBASED_CTLS])); + kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_PINBASED_CTLS, + make_vmx_msr_value(MSR_IA32_VMX_TRUE_PINBASED_CTLS, + f[FEAT_VMX_PINBASED_CTLS])); + kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_EXIT_CTLS, + make_vmx_msr_value(MSR_IA32_VMX_TRUE_EXIT_CTLS, + f[FEAT_VMX_EXIT_CTLS]) | fixed_vm= x_exit); + kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_ENTRY_CTLS, + make_vmx_msr_value(MSR_IA32_VMX_TRUE_ENTRY_CTLS, + f[FEAT_VMX_ENTRY_CTLS])); + kvm_msr_entry_add(cpu, MSR_IA32_VMX_PROCBASED_CTLS2, + make_vmx_msr_value(MSR_IA32_VMX_PROCBASED_CTLS2, + f[FEAT_VMX_SECONDARY_CTLS])); + kvm_msr_entry_add(cpu, MSR_IA32_VMX_EPT_VPID_CAP, + f[FEAT_VMX_EPT_VPID_CAPS] | fixed_vmx_ept_vpid); + kvm_msr_entry_add(cpu, MSR_IA32_VMX_BASIC, + f[FEAT_VMX_BASIC] | fixed_vmx_basic); + kvm_msr_entry_add(cpu, MSR_IA32_VMX_MISC, + f[FEAT_VMX_MISC] | fixed_vmx_misc); + if (has_msr_vmx_vmfunc) { + kvm_msr_entry_add(cpu, MSR_IA32_VMX_VMFUNC, f[FEAT_VMX_VMFUNC]); + } + + /* + * Just to be safe, write these with constant values. The CRn_FIXED1 + * MSRs are generated by KVM based on the vCPU's CPUID. + */ + kvm_msr_entry_add(cpu, MSR_IA32_VMX_CR0_FIXED0, + CR0_PE_MASK | CR0_PG_MASK | CR0_NE_MASK); + kvm_msr_entry_add(cpu, MSR_IA32_VMX_CR4_FIXED0, + CR4_VMXE_MASK); + kvm_msr_entry_add(cpu, MSR_IA32_VMX_VMCS_ENUM, + VMCS12_MAX_FIELD_INDEX << 1); +} + static int kvm_put_msrs(X86CPU *cpu, int level) { CPUX86State *env =3D &cpu->env; @@ -2659,6 +2802,13 @@ static int kvm_put_msrs(X86CPU *cpu, int level) kvm_msr_entry_add(cpu, MSR_MC0_CTL + i, env->mce_banks[i]); } } + /* + * Older kernels do not include VMX MSRs in KVM_GET_MSR_INDEX_LIST, but + * all kernels with MSR features should have them. + */ + if (kvm_feature_msrs && cpu_has_vmx(env)) { + kvm_msr_entry_add_vmx(cpu, env->features); + } =20 ret =3D kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); if (ret < 0) { --=20 1.8.3.1