|
|
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 |
|