yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
016a62
From 88ab13cec526a16cb02bf1af51bdd33230308d36 Mon Sep 17 00:00:00 2001
016a62
From: Paolo Bonzini <pbonzini@redhat.com>
016a62
Date: Fri, 22 Nov 2019 11:53:44 +0000
016a62
Subject: [PATCH 11/16] target/i386: add VMX features
016a62
016a62
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
016a62
Message-id: <20191122115348.25000-12-pbonzini@redhat.com>
016a62
Patchwork-id: 92608
016a62
O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 11/15] target/i386: add VMX features
016a62
Bugzilla: 1689270
016a62
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
016a62
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
016a62
RH-Acked-by: Maxim Levitsky <mlevitsk@redhat.com>
016a62
016a62
Add code to convert the VMX feature words back into MSR values,
016a62
allowing the user to enable/disable VMX features as they wish.  The same
016a62
infrastructure enables support for limiting VMX features in named
016a62
CPU models.
016a62
016a62
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
016a62
(cherry picked from commit 20a78b02d31534ae478779c2f2816c273601e869)
016a62
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
016a62
---
016a62
 target/i386/cpu.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
016a62
 target/i386/cpu.h |   9 +++
016a62
 target/i386/kvm.c | 162 ++++++++++++++++++++++++++++++++++++++-
016a62
 3 files changed, 394 insertions(+), 2 deletions(-)
016a62
016a62
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
016a62
index 3e77830..9074a2e 100644
016a62
--- a/target/i386/cpu.c
016a62
+++ b/target/i386/cpu.c
016a62
@@ -1171,6 +1171,163 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
016a62
             .index = MSR_IA32_CORE_CAPABILITY,
016a62
         },
016a62
     },
016a62
+
016a62
+    [FEAT_VMX_PROCBASED_CTLS] = {
016a62
+        .type = MSR_FEATURE_WORD,
016a62
+        .feat_names = {
016a62
+            NULL, NULL, "vmx-vintr-pending", "vmx-tsc-offset",
016a62
+            NULL, NULL, NULL, "vmx-hlt-exit",
016a62
+            NULL, "vmx-invlpg-exit", "vmx-mwait-exit", "vmx-rdpmc-exit",
016a62
+            "vmx-rdtsc-exit", NULL, NULL, "vmx-cr3-load-noexit",
016a62
+            "vmx-cr3-store-noexit", NULL, NULL, "vmx-cr8-load-exit",
016a62
+            "vmx-cr8-store-exit", "vmx-flexpriority", "vmx-vnmi-pending", "vmx-movdr-exit",
016a62
+            "vmx-io-exit", "vmx-io-bitmap", NULL, "vmx-mtf",
016a62
+            "vmx-msr-bitmap", "vmx-monitor-exit", "vmx-pause-exit", "vmx-secondary-ctls",
016a62
+        },
016a62
+        .msr = {
016a62
+            .index = MSR_IA32_VMX_TRUE_PROCBASED_CTLS,
016a62
+        }
016a62
+    },
016a62
+
016a62
+    [FEAT_VMX_SECONDARY_CTLS] = {
016a62
+        .type = MSR_FEATURE_WORD,
016a62
+        .feat_names = {
016a62
+            "vmx-apicv-xapic", "vmx-ept", "vmx-desc-exit", "vmx-rdtscp-exit",
016a62
+            "vmx-apicv-x2apic", "vmx-vpid", "vmx-wbinvd-exit", "vmx-unrestricted-guest",
016a62
+            "vmx-apicv-register", "vmx-apicv-vid", "vmx-ple", "vmx-rdrand-exit",
016a62
+            "vmx-invpcid-exit", "vmx-vmfunc", "vmx-shadow-vmcs", "vmx-encls-exit",
016a62
+            "vmx-rdseed-exit", "vmx-pml", NULL, NULL,
016a62
+            "vmx-xsaves", NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+        },
016a62
+        .msr = {
016a62
+            .index = MSR_IA32_VMX_PROCBASED_CTLS2,
016a62
+        }
016a62
+    },
016a62
+
016a62
+    [FEAT_VMX_PINBASED_CTLS] = {
016a62
+        .type = MSR_FEATURE_WORD,
016a62
+        .feat_names = {
016a62
+            "vmx-intr-exit", NULL, NULL, "vmx-nmi-exit",
016a62
+            NULL, "vmx-vnmi", "vmx-preemption-timer", "vmx-posted-intr",
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+        },
016a62
+        .msr = {
016a62
+            .index = MSR_IA32_VMX_TRUE_PINBASED_CTLS,
016a62
+        }
016a62
+    },
016a62
+
016a62
+    [FEAT_VMX_EXIT_CTLS] = {
016a62
+        .type = MSR_FEATURE_WORD,
016a62
+        /*
016a62
+         * VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE is copied from
016a62
+         * the LM CPUID bit.
016a62
+         */
016a62
+        .feat_names = {
016a62
+            NULL, NULL, "vmx-exit-nosave-debugctl", NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL /* vmx-exit-host-addr-space-size */, NULL, NULL,
016a62
+            "vmx-exit-load-perf-global-ctrl", NULL, NULL, "vmx-exit-ack-intr",
016a62
+            NULL, NULL, "vmx-exit-save-pat", "vmx-exit-load-pat",
016a62
+            "vmx-exit-save-efer", "vmx-exit-load-efer",
016a62
+                "vmx-exit-save-preemption-timer", "vmx-exit-clear-bndcfgs",
016a62
+            NULL, "vmx-exit-clear-rtit-ctl", NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+        },
016a62
+        .msr = {
016a62
+            .index = MSR_IA32_VMX_TRUE_EXIT_CTLS,
016a62
+        }
016a62
+    },
016a62
+
016a62
+    [FEAT_VMX_ENTRY_CTLS] = {
016a62
+        .type = MSR_FEATURE_WORD,
016a62
+        .feat_names = {
016a62
+            NULL, NULL, "vmx-entry-noload-debugctl", NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, "vmx-entry-ia32e-mode", NULL, NULL,
016a62
+            NULL, "vmx-entry-load-perf-global-ctrl", "vmx-entry-load-pat", "vmx-entry-load-efer",
016a62
+            "vmx-entry-load-bndcfgs", NULL, "vmx-entry-load-rtit-ctl", NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+        },
016a62
+        .msr = {
016a62
+            .index = MSR_IA32_VMX_TRUE_ENTRY_CTLS,
016a62
+        }
016a62
+    },
016a62
+
016a62
+    [FEAT_VMX_MISC] = {
016a62
+        .type = MSR_FEATURE_WORD,
016a62
+        .feat_names = {
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, "vmx-store-lma", "vmx-activity-hlt", "vmx-activity-shutdown",
016a62
+            "vmx-activity-wait-sipi", NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, "vmx-vmwrite-vmexit-fields", "vmx-zero-len-inject", NULL,
016a62
+        },
016a62
+        .msr = {
016a62
+            .index = MSR_IA32_VMX_MISC,
016a62
+        }
016a62
+    },
016a62
+
016a62
+    [FEAT_VMX_EPT_VPID_CAPS] = {
016a62
+        .type = MSR_FEATURE_WORD,
016a62
+        .feat_names = {
016a62
+            "vmx-ept-execonly", NULL, NULL, NULL,
016a62
+            NULL, NULL, "vmx-page-walk-4", "vmx-page-walk-5",
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            "vmx-ept-2mb", "vmx-ept-1gb", NULL, NULL,
016a62
+            "vmx-invept", "vmx-eptad", "vmx-ept-advanced-exitinfo", NULL,
016a62
+            NULL, "vmx-invept-single-context", "vmx-invept-all-context", NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            "vmx-invvpid", NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            "vmx-invvpid-single-addr", "vmx-invept-single-context",
016a62
+                "vmx-invvpid-all-context", "vmx-invept-single-context-noglobals",
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+            NULL, NULL, NULL, NULL,
016a62
+        },
016a62
+        .msr = {
016a62
+            .index = MSR_IA32_VMX_EPT_VPID_CAP,
016a62
+        }
016a62
+    },
016a62
+
016a62
+    [FEAT_VMX_BASIC] = {
016a62
+        .type = MSR_FEATURE_WORD,
016a62
+        .feat_names = {
016a62
+            [54] = "vmx-ins-outs",
016a62
+            [55] = "vmx-true-ctls",
016a62
+        },
016a62
+        .msr = {
016a62
+            .index = MSR_IA32_VMX_BASIC,
016a62
+        },
016a62
+        /* Just to be safe - we don't support setting the MSEG version field.  */
016a62
+        .no_autoenable_flags = MSR_VMX_BASIC_DUAL_MONITOR,
016a62
+    },
016a62
+
016a62
+    [FEAT_VMX_VMFUNC] = {
016a62
+        .type = MSR_FEATURE_WORD,
016a62
+        .feat_names = {
016a62
+            [0] = "vmx-eptp-switching",
016a62
+        },
016a62
+        .msr = {
016a62
+            .index = MSR_IA32_VMX_VMFUNC,
016a62
+        }
016a62
+    },
016a62
+
016a62
 };
016a62
 
016a62
 typedef struct FeatureMask {
016a62
@@ -1191,6 +1348,74 @@ static FeatureDep feature_dependencies[] = {
016a62
         .from = { FEAT_7_0_EDX,             CPUID_7_0_EDX_CORE_CAPABILITY },
016a62
         .to = { FEAT_CORE_CAPABILITY,       ~0ull },
016a62
     },
016a62
+    {
016a62
+        .from = { FEAT_1_ECX,               CPUID_EXT_VMX },
016a62
+        .to = { FEAT_VMX_PROCBASED_CTLS,    ~0ull },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_1_ECX,               CPUID_EXT_VMX },
016a62
+        .to = { FEAT_VMX_PINBASED_CTLS,     ~0ull },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_1_ECX,               CPUID_EXT_VMX },
016a62
+        .to = { FEAT_VMX_EXIT_CTLS,         ~0ull },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_1_ECX,               CPUID_EXT_VMX },
016a62
+        .to = { FEAT_VMX_ENTRY_CTLS,        ~0ull },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_1_ECX,               CPUID_EXT_VMX },
016a62
+        .to = { FEAT_VMX_MISC,              ~0ull },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_1_ECX,               CPUID_EXT_VMX },
016a62
+        .to = { FEAT_VMX_BASIC,             ~0ull },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_8000_0001_EDX,       CPUID_EXT2_LM },
016a62
+        .to = { FEAT_VMX_ENTRY_CTLS,        VMX_VM_ENTRY_IA32E_MODE },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_VMX_PROCBASED_CTLS,  VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS },
016a62
+        .to = { FEAT_VMX_SECONDARY_CTLS,    ~0ull },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_XSAVE,               CPUID_XSAVE_XSAVES },
016a62
+        .to = { FEAT_VMX_SECONDARY_CTLS,    VMX_SECONDARY_EXEC_XSAVES },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_1_ECX,               CPUID_EXT_RDRAND },
016a62
+        .to = { FEAT_VMX_SECONDARY_CTLS,    VMX_SECONDARY_EXEC_RDRAND_EXITING },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_7_0_EBX,             CPUID_7_0_EBX_INVPCID },
016a62
+        .to = { FEAT_VMX_SECONDARY_CTLS,    VMX_SECONDARY_EXEC_ENABLE_INVPCID },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_7_0_EBX,             CPUID_7_0_EBX_RDSEED },
016a62
+        .to = { FEAT_VMX_SECONDARY_CTLS,    VMX_SECONDARY_EXEC_RDSEED_EXITING },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_8000_0001_EDX,       CPUID_EXT2_RDTSCP },
016a62
+        .to = { FEAT_VMX_SECONDARY_CTLS,    VMX_SECONDARY_EXEC_RDTSCP },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_VMX_SECONDARY_CTLS,  VMX_SECONDARY_EXEC_ENABLE_EPT },
016a62
+        .to = { FEAT_VMX_EPT_VPID_CAPS,     0xffffffffull },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_VMX_SECONDARY_CTLS,  VMX_SECONDARY_EXEC_ENABLE_EPT },
016a62
+        .to = { FEAT_VMX_SECONDARY_CTLS,    VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_VMX_SECONDARY_CTLS,  VMX_SECONDARY_EXEC_ENABLE_VPID },
016a62
+        .to = { FEAT_VMX_EPT_VPID_CAPS,     0xffffffffull << 32 },
016a62
+    },
016a62
+    {
016a62
+        .from = { FEAT_VMX_SECONDARY_CTLS,  VMX_SECONDARY_EXEC_ENABLE_VMFUNC },
016a62
+        .to = { FEAT_VMX_VMFUNC,            ~0ull },
016a62
+    },
016a62
 };
016a62
 
016a62
 typedef struct X86RegisterInfo32 {
016a62
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
016a62
index 2d1f247..386e821 100644
016a62
--- a/target/i386/cpu.h
016a62
+++ b/target/i386/cpu.h
016a62
@@ -522,6 +522,15 @@ typedef enum FeatureWord {
016a62
     FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
016a62
     FEAT_ARCH_CAPABILITIES,
016a62
     FEAT_CORE_CAPABILITY,
016a62
+    FEAT_VMX_PROCBASED_CTLS,
016a62
+    FEAT_VMX_SECONDARY_CTLS,
016a62
+    FEAT_VMX_PINBASED_CTLS,
016a62
+    FEAT_VMX_EXIT_CTLS,
016a62
+    FEAT_VMX_ENTRY_CTLS,
016a62
+    FEAT_VMX_MISC,
016a62
+    FEAT_VMX_EPT_VPID_CAPS,
016a62
+    FEAT_VMX_BASIC,
016a62
+    FEAT_VMX_VMFUNC,
016a62
     FEATURE_WORDS,
016a62
 } FeatureWord;
016a62
 
016a62
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
016a62
index 85abd37..512d7d5 100644
016a62
--- a/target/i386/kvm.c
016a62
+++ b/target/i386/kvm.c
016a62
@@ -96,6 +96,7 @@ static bool has_msr_virt_ssbd;
016a62
 static bool has_msr_smi_count;
016a62
 static bool has_msr_arch_capabs;
016a62
 static bool has_msr_core_capabs;
016a62
+static bool has_msr_vmx_vmfunc;
016a62
 
016a62
 static uint32_t has_architectural_pmu_version;
016a62
 static uint32_t num_architectural_pmu_gp_counters;
016a62
@@ -429,7 +430,8 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index)
016a62
         struct kvm_msrs info;
016a62
         struct kvm_msr_entry entries[1];
016a62
     } msr_data;
016a62
-    uint32_t ret;
016a62
+    uint64_t value;
016a62
+    uint32_t ret, can_be_one, must_be_one;
016a62
 
016a62
     if (kvm_feature_msrs == NULL) { /* Host doesn't support feature MSRs */
016a62
         return 0;
016a62
@@ -455,7 +457,25 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index)
016a62
         exit(1);
016a62
     }
016a62
 
016a62
-    return msr_data.entries[0].data;
016a62
+    value = msr_data.entries[0].data;
016a62
+    switch (index) {
016a62
+    case MSR_IA32_VMX_PROCBASED_CTLS2:
016a62
+    case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
016a62
+    case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
016a62
+    case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
016a62
+    case MSR_IA32_VMX_TRUE_EXIT_CTLS:
016a62
+        /*
016a62
+         * Return true for bits that can be one, but do not have to be one.
016a62
+         * The SDM tells us which bits could have a "must be one" setting,
016a62
+         * so we can do the opposite transformation in make_vmx_msr_value.
016a62
+         */
016a62
+        must_be_one = (uint32_t)value;
016a62
+        can_be_one = (uint32_t)(value >> 32);
016a62
+        return can_be_one & ~must_be_one;
016a62
+
016a62
+    default:
016a62
+        return value;
016a62
+    }
016a62
 }
016a62
 
016a62
 
016a62
@@ -1430,6 +1450,9 @@ static int kvm_get_supported_msrs(KVMState *s)
016a62
             case MSR_IA32_CORE_CAPABILITY:
016a62
                 has_msr_core_capabs = true;
016a62
                 break;
016a62
+            case MSR_IA32_VMX_VMFUNC:
016a62
+                has_msr_vmx_vmfunc = true;
016a62
+                break;
016a62
             }
016a62
         }
016a62
     }
016a62
@@ -1886,6 +1909,132 @@ static int kvm_put_msr_feature_control(X86CPU *cpu)
016a62
     return 0;
016a62
 }
016a62
 
016a62
+static uint64_t make_vmx_msr_value(uint32_t index, uint32_t features)
016a62
+{
016a62
+    uint32_t default1, can_be_one, can_be_zero;
016a62
+    uint32_t must_be_one;
016a62
+
016a62
+    switch (index) {
016a62
+    case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
016a62
+        default1 = 0x00000016;
016a62
+        break;
016a62
+    case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
016a62
+        default1 = 0x0401e172;
016a62
+        break;
016a62
+    case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
016a62
+        default1 = 0x000011ff;
016a62
+        break;
016a62
+    case MSR_IA32_VMX_TRUE_EXIT_CTLS:
016a62
+        default1 = 0x00036dff;
016a62
+        break;
016a62
+    case MSR_IA32_VMX_PROCBASED_CTLS2:
016a62
+        default1 = 0;
016a62
+        break;
016a62
+    default:
016a62
+        abort();
016a62
+    }
016a62
+
016a62
+    /* If a feature bit is set, the control can be either set or clear.
016a62
+     * Otherwise the value is limited to either 0 or 1 by default1.
016a62
+     */
016a62
+    can_be_one = features | default1;
016a62
+    can_be_zero = features | ~default1;
016a62
+    must_be_one = ~can_be_zero;
016a62
+
016a62
+    /*
016a62
+     * Bit 0:31 -> 0 if the control bit can be zero (i.e. 1 if it must be one).
016a62
+     * Bit 32:63 -> 1 if the control bit can be one.
016a62
+     */
016a62
+    return must_be_one | (((uint64_t)can_be_one) << 32);
016a62
+}
016a62
+
016a62
+#define VMCS12_MAX_FIELD_INDEX (0x17)
016a62
+
016a62
+static void kvm_msr_entry_add_vmx(X86CPU *cpu, FeatureWordArray f)
016a62
+{
016a62
+    uint64_t kvm_vmx_basic =
016a62
+        kvm_arch_get_supported_msr_feature(kvm_state,
016a62
+                                           MSR_IA32_VMX_BASIC);
016a62
+    uint64_t kvm_vmx_misc =
016a62
+        kvm_arch_get_supported_msr_feature(kvm_state,
016a62
+                                           MSR_IA32_VMX_MISC);
016a62
+    uint64_t kvm_vmx_ept_vpid =
016a62
+        kvm_arch_get_supported_msr_feature(kvm_state,
016a62
+                                           MSR_IA32_VMX_EPT_VPID_CAP);
016a62
+
016a62
+    /*
016a62
+     * If the guest is 64-bit, a value of 1 is allowed for the host address
016a62
+     * space size vmexit control.
016a62
+     */
016a62
+    uint64_t fixed_vmx_exit = f[FEAT_8000_0001_EDX] & CPUID_EXT2_LM
016a62
+        ? (uint64_t)VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE << 32 : 0;
016a62
+
016a62
+    /*
016a62
+     * Bits 0-30, 32-44 and 50-53 come from the host.  KVM should
016a62
+     * not change them for backwards compatibility.
016a62
+     */
016a62
+    uint64_t fixed_vmx_basic = kvm_vmx_basic &
016a62
+        (MSR_VMX_BASIC_VMCS_REVISION_MASK |
016a62
+         MSR_VMX_BASIC_VMXON_REGION_SIZE_MASK |
016a62
+         MSR_VMX_BASIC_VMCS_MEM_TYPE_MASK);
016a62
+
016a62
+    /*
016a62
+     * Same for bits 0-4 and 25-27.  Bits 16-24 (CR3 target count) can
016a62
+     * change in the future but are always zero for now, clear them to be
016a62
+     * future proof.  Bits 32-63 in theory could change, though KVM does
016a62
+     * not support dual-monitor treatment and probably never will; mask
016a62
+     * them out as well.
016a62
+     */
016a62
+    uint64_t fixed_vmx_misc = kvm_vmx_misc &
016a62
+        (MSR_VMX_MISC_PREEMPTION_TIMER_SHIFT_MASK |
016a62
+         MSR_VMX_MISC_MAX_MSR_LIST_SIZE_MASK);
016a62
+
016a62
+    /*
016a62
+     * EPT memory types should not change either, so we do not bother
016a62
+     * adding features for them.
016a62
+     */
016a62
+    uint64_t fixed_vmx_ept_mask =
016a62
+            (f[FEAT_VMX_SECONDARY_CTLS] & VMX_SECONDARY_EXEC_ENABLE_EPT ?
016a62
+             MSR_VMX_EPT_UC | MSR_VMX_EPT_WB : 0);
016a62
+    uint64_t fixed_vmx_ept_vpid = kvm_vmx_ept_vpid & fixed_vmx_ept_mask;
016a62
+
016a62
+    kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS,
016a62
+                      make_vmx_msr_value(MSR_IA32_VMX_TRUE_PROCBASED_CTLS,
016a62
+                                         f[FEAT_VMX_PROCBASED_CTLS]));
016a62
+    kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_PINBASED_CTLS,
016a62
+                      make_vmx_msr_value(MSR_IA32_VMX_TRUE_PINBASED_CTLS,
016a62
+                                         f[FEAT_VMX_PINBASED_CTLS]));
016a62
+    kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_EXIT_CTLS,
016a62
+                      make_vmx_msr_value(MSR_IA32_VMX_TRUE_EXIT_CTLS,
016a62
+                                         f[FEAT_VMX_EXIT_CTLS]) | fixed_vmx_exit);
016a62
+    kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_ENTRY_CTLS,
016a62
+                      make_vmx_msr_value(MSR_IA32_VMX_TRUE_ENTRY_CTLS,
016a62
+                                         f[FEAT_VMX_ENTRY_CTLS]));
016a62
+    kvm_msr_entry_add(cpu, MSR_IA32_VMX_PROCBASED_CTLS2,
016a62
+                      make_vmx_msr_value(MSR_IA32_VMX_PROCBASED_CTLS2,
016a62
+                                         f[FEAT_VMX_SECONDARY_CTLS]));
016a62
+    kvm_msr_entry_add(cpu, MSR_IA32_VMX_EPT_VPID_CAP,
016a62
+                      f[FEAT_VMX_EPT_VPID_CAPS] | fixed_vmx_ept_vpid);
016a62
+    kvm_msr_entry_add(cpu, MSR_IA32_VMX_BASIC,
016a62
+                      f[FEAT_VMX_BASIC] | fixed_vmx_basic);
016a62
+    kvm_msr_entry_add(cpu, MSR_IA32_VMX_MISC,
016a62
+                      f[FEAT_VMX_MISC] | fixed_vmx_misc);
016a62
+    if (has_msr_vmx_vmfunc) {
016a62
+        kvm_msr_entry_add(cpu, MSR_IA32_VMX_VMFUNC, f[FEAT_VMX_VMFUNC]);
016a62
+    }
016a62
+
016a62
+    /*
016a62
+     * Just to be safe, write these with constant values.  The CRn_FIXED1
016a62
+     * MSRs are generated by KVM based on the vCPU's CPUID.
016a62
+     */
016a62
+    kvm_msr_entry_add(cpu, MSR_IA32_VMX_CR0_FIXED0,
016a62
+                      CR0_PE_MASK | CR0_PG_MASK | CR0_NE_MASK);
016a62
+    kvm_msr_entry_add(cpu, MSR_IA32_VMX_CR4_FIXED0,
016a62
+                      CR4_VMXE_MASK);
016a62
+    kvm_msr_entry_add(cpu, MSR_IA32_VMX_VMCS_ENUM,
016a62
+                      VMCS12_MAX_FIELD_INDEX << 1);
016a62
+}
016a62
+
016a62
 static int kvm_put_msrs(X86CPU *cpu, int level)
016a62
 {
016a62
     CPUX86State *env = &cpu->env;
016a62
@@ -2112,7 +2261,16 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
016a62
 
016a62
         /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see
016a62
          *       kvm_put_msr_feature_control. */
016a62
+
016a62
+        /*
016a62
+         * Older kernels do not include VMX MSRs in KVM_GET_MSR_INDEX_LIST, but
016a62
+         * all kernels with MSR features should have them.
016a62
+         */
016a62
+        if (kvm_feature_msrs && cpu_has_vmx(env)) {
016a62
+            kvm_msr_entry_add_vmx(cpu, env->features);
016a62
+        }
016a62
     }
016a62
+
016a62
     if (env->mcg_cap) {
016a62
         int i;
016a62
 
016a62
-- 
016a62
1.8.3.1
016a62