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