Blame SOURCES/kvm-target-i386-introduce-generic-feature-dependency-mec.patch

4ec855
From 98145bfcdcee809e370d65eb3a97a9529670ec06 Mon Sep 17 00:00:00 2001
4ec855
From: Paolo Bonzini <pbonzini@redhat.com>
4ec855
Date: Fri, 22 Nov 2019 11:53:40 +0000
4ec855
Subject: [PATCH 07/16] target/i386: introduce generic feature dependency
4ec855
 mechanism
4ec855
4ec855
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
4ec855
Message-id: <20191122115348.25000-8-pbonzini@redhat.com>
4ec855
Patchwork-id: 92610
4ec855
O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 07/15] target/i386: introduce generic feature dependency mechanism
4ec855
Bugzilla: 1689270
4ec855
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
4ec855
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
4ec855
RH-Acked-by: Maxim Levitsky <mlevitsk@redhat.com>
4ec855
4ec855
Sometimes a CPU feature does not make sense unless another is
4ec855
present.  In the case of VMX features, KVM does not even allow
4ec855
setting the VMX controls to some invalid combinations.
4ec855
4ec855
Therefore, this patch adds a generic mechanism that looks for bits
4ec855
that the user explicitly cleared, and uses them to remove other bits
4ec855
from the expanded CPU definition.  If these dependent bits were also
4ec855
explicitly *set* by the user, this will be a warning for "-cpu check"
4ec855
and an error for "-cpu enforce".  If not, then the dependent bits are
4ec855
cleared silently, for convenience.
4ec855
4ec855
With VMX features, this will be used so that for example
4ec855
"-cpu host,-rdrand" will also hide support for RDRAND exiting.
4ec855
4ec855
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4ec855
(cherry picked from commit 99e24dbdaa682c7b9d0bb5b463638c585bcee1c3)
4ec855
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
4ec855
---
4ec855
 target/i386/cpu.c | 72 ++++++++++++++++++++++++++++++++++++-------------------
4ec855
 1 file changed, 48 insertions(+), 24 deletions(-)
4ec855
4ec855
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
4ec855
index b06ce9d..a7360b3 100644
4ec855
--- a/target/i386/cpu.c
4ec855
+++ b/target/i386/cpu.c
4ec855
@@ -797,10 +797,6 @@ typedef struct FeatureWordInfo {
4ec855
         /* If type==MSR_FEATURE_WORD */
4ec855
         struct {
4ec855
             uint32_t index;
4ec855
-            struct {   /*CPUID that enumerate this MSR*/
4ec855
-                FeatureWord cpuid_class;
4ec855
-                uint32_t    cpuid_flag;
4ec855
-            } cpuid_dep;
4ec855
         } msr;
4ec855
     };
4ec855
     uint32_t tcg_features; /* Feature flags supported by TCG */
4ec855
@@ -1157,10 +1153,6 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
4ec855
         },
4ec855
         .msr = {
4ec855
             .index = MSR_IA32_ARCH_CAPABILITIES,
4ec855
-            .cpuid_dep = {
4ec855
-                FEAT_7_0_EDX,
4ec855
-                CPUID_7_0_EDX_ARCH_CAPABILITIES
4ec855
-            }
4ec855
         },
4ec855
     },
4ec855
     [FEAT_CORE_CAPABILITY] = {
4ec855
@@ -1177,14 +1169,30 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
4ec855
         },
4ec855
         .msr = {
4ec855
             .index = MSR_IA32_CORE_CAPABILITY,
4ec855
-            .cpuid_dep = {
4ec855
-                FEAT_7_0_EDX,
4ec855
-                CPUID_7_0_EDX_CORE_CAPABILITY,
4ec855
-            },
4ec855
         },
4ec855
     },
4ec855
 };
4ec855
 
4ec855
+typedef struct FeatureMask {
4ec855
+    FeatureWord index;
4ec855
+    uint32_t mask;
4ec855
+} FeatureMask;
4ec855
+
4ec855
+typedef struct FeatureDep {
4ec855
+    FeatureMask from, to;
4ec855
+} FeatureDep;
4ec855
+
4ec855
+static FeatureDep feature_dependencies[] = {
4ec855
+    {
4ec855
+        .from = { FEAT_7_0_EDX,             CPUID_7_0_EDX_ARCH_CAPABILITIES },
4ec855
+        .to = { FEAT_ARCH_CAPABILITIES,     ~0u },
4ec855
+    },
4ec855
+    {
4ec855
+        .from = { FEAT_7_0_EDX,             CPUID_7_0_EDX_CORE_CAPABILITY },
4ec855
+        .to = { FEAT_CORE_CAPABILITY,       ~0u },
4ec855
+    },
4ec855
+};
4ec855
+
4ec855
 typedef struct X86RegisterInfo32 {
4ec855
     /* Name of register */
4ec855
     const char *name;
4ec855
@@ -4967,9 +4975,26 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
4ec855
 {
4ec855
     CPUX86State *env = &cpu->env;
4ec855
     FeatureWord w;
4ec855
+    int i;
4ec855
     GList *l;
4ec855
     Error *local_err = NULL;
4ec855
 
4ec855
+    for (l = plus_features; l; l = l->next) {
4ec855
+        const char *prop = l->data;
4ec855
+        object_property_set_bool(OBJECT(cpu), true, prop, &local_err);
4ec855
+        if (local_err) {
4ec855
+            goto out;
4ec855
+        }
4ec855
+    }
4ec855
+
4ec855
+    for (l = minus_features; l; l = l->next) {
4ec855
+        const char *prop = l->data;
4ec855
+        object_property_set_bool(OBJECT(cpu), false, prop, &local_err);
4ec855
+        if (local_err) {
4ec855
+            goto out;
4ec855
+        }
4ec855
+    }
4ec855
+
4ec855
     /*TODO: Now cpu->max_features doesn't overwrite features
4ec855
      * set using QOM properties, and we can convert
4ec855
      * plus_features & minus_features to global properties
4ec855
@@ -4987,19 +5012,18 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
4ec855
         }
4ec855
     }
4ec855
 
4ec855
-    for (l = plus_features; l; l = l->next) {
4ec855
-        const char *prop = l->data;
4ec855
-        object_property_set_bool(OBJECT(cpu), true, prop, &local_err);
4ec855
-        if (local_err) {
4ec855
-            goto out;
4ec855
-        }
4ec855
-    }
4ec855
+    for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) {
4ec855
+        FeatureDep *d = &feature_dependencies[i];
4ec855
+        if (!(env->features[d->from.index] & d->from.mask)) {
4ec855
+            uint32_t unavailable_features = env->features[d->to.index] & d->to.mask;
4ec855
 
4ec855
-    for (l = minus_features; l; l = l->next) {
4ec855
-        const char *prop = l->data;
4ec855
-        object_property_set_bool(OBJECT(cpu), false, prop, &local_err);
4ec855
-        if (local_err) {
4ec855
-            goto out;
4ec855
+            /* Not an error unless the dependent feature was added explicitly.  */
4ec855
+            mark_unavailable_features(cpu, d->to.index,
4ec855
+                                      unavailable_features & env->user_features[d->to.index],
4ec855
+                                      "This feature depends on other features that were not requested");
4ec855
+
4ec855
+            env->user_features[d->to.index] |= unavailable_features;
4ec855
+            env->features[d->to.index] &= ~unavailable_features;
4ec855
         }
4ec855
     }
4ec855
 
4ec855
-- 
4ec855
1.8.3.1
4ec855