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

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