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