Pablo Greco e6a3ae
From c4660f9a4e2ffde711294ee7c5959f17735fd863 Mon Sep 17 00:00:00 2001
Pablo Greco e6a3ae
From: Paolo Bonzini <pbonzini@redhat.com>
Pablo Greco e6a3ae
Date: Thu, 6 Feb 2020 23:51:16 +0000
Pablo Greco e6a3ae
Subject: [PATCH 2/2] target/i386: kvm: initialize feature MSRs very early
Pablo Greco e6a3ae
Pablo Greco e6a3ae
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
Pablo Greco e6a3ae
Message-id: <20200206235116.19421-2-pbonzini@redhat.com>
Pablo Greco e6a3ae
Patchwork-id: 93733
Pablo Greco e6a3ae
O-Subject: [PATCH 1/1] target/i386: kvm: initialize feature MSRs very early
Pablo Greco e6a3ae
Bugzilla: 1790308
Pablo Greco e6a3ae
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Some read-only MSRs affect the behavior of ioctls such as
Pablo Greco e6a3ae
KVM_SET_NESTED_STATE.  We can initialize them once and for all
Pablo Greco e6a3ae
right after the CPU is realized, since they will never be modified
Pablo Greco e6a3ae
by the guest.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Reported-by: Qingua Cheng <qcheng@redhat.com>
Pablo Greco e6a3ae
Cc: qemu-stable@nongnu.org
Pablo Greco e6a3ae
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Pablo Greco e6a3ae
Message-Id: <1579544504-3616-2-git-send-email-pbonzini@redhat.com>
Pablo Greco e6a3ae
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Pablo Greco e6a3ae
(cherry picked from commit 420ae1fc51c99abfd03b1c590f55617edd2a2bed)
Pablo Greco e6a3ae
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Pablo Greco e6a3ae
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
Pablo Greco e6a3ae
---
Pablo Greco e6a3ae
 target/i386/kvm.c      | 81 ++++++++++++++++++++++++++++++--------------------
Pablo Greco e6a3ae
 target/i386/kvm_i386.h |  1 +
Pablo Greco e6a3ae
 2 files changed, 49 insertions(+), 33 deletions(-)
Pablo Greco e6a3ae
Pablo Greco e6a3ae
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
Pablo Greco e6a3ae
index 92eda8d..e43bcd3 100644
Pablo Greco e6a3ae
--- a/target/i386/kvm.c
Pablo Greco e6a3ae
+++ b/target/i386/kvm.c
Pablo Greco e6a3ae
@@ -65,6 +65,8 @@
Pablo Greco e6a3ae
  * 255 kvm_msr_entry structs */
Pablo Greco e6a3ae
 #define MSR_BUF_SIZE 4096
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
+static void kvm_init_msrs(X86CPU *cpu);
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
Pablo Greco e6a3ae
     KVM_CAP_INFO(SET_TSS_ADDR),
Pablo Greco e6a3ae
     KVM_CAP_INFO(EXT_CPUID),
Pablo Greco e6a3ae
@@ -1296,6 +1298,8 @@ int kvm_arch_init_vcpu(CPUState *cs)
Pablo Greco e6a3ae
         has_msr_tsc_aux = false;
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
+    kvm_init_msrs(cpu);
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
     return 0;
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
  fail:
Pablo Greco e6a3ae
@@ -2099,11 +2103,53 @@ static void kvm_msr_entry_add_vmx(X86CPU *cpu, FeatureWordArray f)
Pablo Greco e6a3ae
                       VMCS12_MAX_FIELD_INDEX << 1);
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
+static int kvm_buf_set_msrs(X86CPU *cpu)
Pablo Greco e6a3ae
+{
Pablo Greco e6a3ae
+    int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
Pablo Greco e6a3ae
+    if (ret < 0) {
Pablo Greco e6a3ae
+        return ret;
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    if (ret < cpu->kvm_msr_buf->nmsrs) {
Pablo Greco e6a3ae
+        struct kvm_msr_entry *e = &cpu->kvm_msr_buf->entries[ret];
Pablo Greco e6a3ae
+        error_report("error: failed to set MSR 0x%" PRIx32 " to 0x%" PRIx64,
Pablo Greco e6a3ae
+                     (uint32_t)e->index, (uint64_t)e->data);
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    assert(ret == cpu->kvm_msr_buf->nmsrs);
Pablo Greco e6a3ae
+    return 0;
Pablo Greco e6a3ae
+}
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+static void kvm_init_msrs(X86CPU *cpu)
Pablo Greco e6a3ae
+{
Pablo Greco e6a3ae
+    CPUX86State *env = &cpu->env;
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    kvm_msr_buf_reset(cpu);
Pablo Greco e6a3ae
+    if (has_msr_arch_capabs) {
Pablo Greco e6a3ae
+        kvm_msr_entry_add(cpu, MSR_IA32_ARCH_CAPABILITIES,
Pablo Greco e6a3ae
+                          env->features[FEAT_ARCH_CAPABILITIES]);
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    if (has_msr_core_capabs) {
Pablo Greco e6a3ae
+        kvm_msr_entry_add(cpu, MSR_IA32_CORE_CAPABILITY,
Pablo Greco e6a3ae
+                          env->features[FEAT_CORE_CAPABILITY]);
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    /*
Pablo Greco e6a3ae
+     * Older kernels do not include VMX MSRs in KVM_GET_MSR_INDEX_LIST, but
Pablo Greco e6a3ae
+     * all kernels with MSR features should have them.
Pablo Greco e6a3ae
+     */
Pablo Greco e6a3ae
+    if (kvm_feature_msrs && cpu_has_vmx(env)) {
Pablo Greco e6a3ae
+        kvm_msr_entry_add_vmx(cpu, env->features);
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    assert(kvm_buf_set_msrs(cpu) == 0);
Pablo Greco e6a3ae
+}
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
 static int kvm_put_msrs(X86CPU *cpu, int level)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
     CPUX86State *env = &cpu->env;
Pablo Greco e6a3ae
     int i;
Pablo Greco e6a3ae
-    int ret;
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     kvm_msr_buf_reset(cpu);
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
@@ -2161,17 +2207,6 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 #endif
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-    /* If host supports feature MSR, write down. */
Pablo Greco e6a3ae
-    if (has_msr_arch_capabs) {
Pablo Greco e6a3ae
-        kvm_msr_entry_add(cpu, MSR_IA32_ARCH_CAPABILITIES,
Pablo Greco e6a3ae
-                          env->features[FEAT_ARCH_CAPABILITIES]);
Pablo Greco e6a3ae
-    }
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-    if (has_msr_core_capabs) {
Pablo Greco e6a3ae
-        kvm_msr_entry_add(cpu, MSR_IA32_CORE_CAPABILITY,
Pablo Greco e6a3ae
-                          env->features[FEAT_CORE_CAPABILITY]);
Pablo Greco e6a3ae
-    }
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
     /*
Pablo Greco e6a3ae
      * The following MSRs have side effects on the guest or are too heavy
Pablo Greco e6a3ae
      * for normal writeback. Limit them to reset or full state updates.
Pablo Greco e6a3ae
@@ -2331,14 +2366,6 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
         /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see
Pablo Greco e6a3ae
          *       kvm_put_msr_feature_control. */
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-        /*
Pablo Greco e6a3ae
-         * Older kernels do not include VMX MSRs in KVM_GET_MSR_INDEX_LIST, but
Pablo Greco e6a3ae
-         * all kernels with MSR features should have them.
Pablo Greco e6a3ae
-         */
Pablo Greco e6a3ae
-        if (kvm_feature_msrs && cpu_has_vmx(env)) {
Pablo Greco e6a3ae
-            kvm_msr_entry_add_vmx(cpu, env->features);
Pablo Greco e6a3ae
-        }
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     if (env->mcg_cap) {
Pablo Greco e6a3ae
@@ -2354,19 +2381,7 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
Pablo Greco e6a3ae
         }
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-    ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
Pablo Greco e6a3ae
-    if (ret < 0) {
Pablo Greco e6a3ae
-        return ret;
Pablo Greco e6a3ae
-    }
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-    if (ret < cpu->kvm_msr_buf->nmsrs) {
Pablo Greco e6a3ae
-        struct kvm_msr_entry *e = &cpu->kvm_msr_buf->entries[ret];
Pablo Greco e6a3ae
-        error_report("error: failed to set MSR 0x%" PRIx32 " to 0x%" PRIx64,
Pablo Greco e6a3ae
-                     (uint32_t)e->index, (uint64_t)e->data);
Pablo Greco e6a3ae
-    }
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-    assert(ret == cpu->kvm_msr_buf->nmsrs);
Pablo Greco e6a3ae
-    return 0;
Pablo Greco e6a3ae
+    return kvm_buf_set_msrs(cpu);
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
diff --git a/target/i386/kvm_i386.h b/target/i386/kvm_i386.h
Pablo Greco e6a3ae
index df9bbf3..5748337 100644
Pablo Greco e6a3ae
--- a/target/i386/kvm_i386.h
Pablo Greco e6a3ae
+++ b/target/i386/kvm_i386.h
Pablo Greco e6a3ae
@@ -70,4 +70,5 @@ void kvm_put_apicbase(X86CPU *cpu, uint64_t value);
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 bool kvm_enable_x2apic(void);
Pablo Greco e6a3ae
 bool kvm_has_x2apic_api(void);
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
 #endif
Pablo Greco e6a3ae
-- 
Pablo Greco e6a3ae
1.8.3.1
Pablo Greco e6a3ae