mirror of https://gitee.com/openkylin/qemu.git
target/i386: expand feature words to 64 bits
VMX requires 64-bit feature words for the IA32_VMX_EPT_VPID_CAP and IA32_VMX_BASIC MSRs. (The VMX control MSRs are 64-bit wide but actually have only 32 bits of information). Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
99e24dbdaa
commit
ede146c2e7
|
@ -462,7 +462,7 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension);
|
||||||
|
|
||||||
uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
|
uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
|
||||||
uint32_t index, int reg);
|
uint32_t index, int reg);
|
||||||
uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index);
|
uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index);
|
||||||
|
|
||||||
|
|
||||||
void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len);
|
void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len);
|
||||||
|
|
|
@ -789,7 +789,7 @@ typedef struct FeatureWordInfo {
|
||||||
* In cases of disagreement between feature naming conventions,
|
* In cases of disagreement between feature naming conventions,
|
||||||
* aliases may be added.
|
* aliases may be added.
|
||||||
*/
|
*/
|
||||||
const char *feat_names[32];
|
const char *feat_names[64];
|
||||||
union {
|
union {
|
||||||
/* If type==CPUID_FEATURE_WORD */
|
/* If type==CPUID_FEATURE_WORD */
|
||||||
struct {
|
struct {
|
||||||
|
@ -803,11 +803,11 @@ typedef struct FeatureWordInfo {
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
} msr;
|
} msr;
|
||||||
};
|
};
|
||||||
uint32_t tcg_features; /* Feature flags supported by TCG */
|
uint64_t tcg_features; /* Feature flags supported by TCG */
|
||||||
uint32_t unmigratable_flags; /* Feature flags known to be unmigratable */
|
uint64_t unmigratable_flags; /* Feature flags known to be unmigratable */
|
||||||
uint32_t migratable_flags; /* Feature flags known to be migratable */
|
uint64_t migratable_flags; /* Feature flags known to be migratable */
|
||||||
/* Features that shouldn't be auto-enabled by "-cpu host" */
|
/* Features that shouldn't be auto-enabled by "-cpu host" */
|
||||||
uint32_t no_autoenable_flags;
|
uint64_t no_autoenable_flags;
|
||||||
} FeatureWordInfo;
|
} FeatureWordInfo;
|
||||||
|
|
||||||
static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||||
|
@ -1236,7 +1236,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||||
|
|
||||||
typedef struct FeatureMask {
|
typedef struct FeatureMask {
|
||||||
FeatureWord index;
|
FeatureWord index;
|
||||||
uint32_t mask;
|
uint64_t mask;
|
||||||
} FeatureMask;
|
} FeatureMask;
|
||||||
|
|
||||||
typedef struct FeatureDep {
|
typedef struct FeatureDep {
|
||||||
|
@ -1246,11 +1246,11 @@ typedef struct FeatureDep {
|
||||||
static FeatureDep feature_dependencies[] = {
|
static FeatureDep feature_dependencies[] = {
|
||||||
{
|
{
|
||||||
.from = { FEAT_7_0_EDX, CPUID_7_0_EDX_ARCH_CAPABILITIES },
|
.from = { FEAT_7_0_EDX, CPUID_7_0_EDX_ARCH_CAPABILITIES },
|
||||||
.to = { FEAT_ARCH_CAPABILITIES, ~0u },
|
.to = { FEAT_ARCH_CAPABILITIES, ~0ull },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY },
|
.from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY },
|
||||||
.to = { FEAT_CORE_CAPABILITY, ~0u },
|
.to = { FEAT_CORE_CAPABILITY, ~0ull },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1362,14 +1362,14 @@ const char *get_register_name_32(unsigned int reg)
|
||||||
* Returns the set of feature flags that are supported and migratable by
|
* Returns the set of feature flags that are supported and migratable by
|
||||||
* QEMU, for a given FeatureWord.
|
* QEMU, for a given FeatureWord.
|
||||||
*/
|
*/
|
||||||
static uint32_t x86_cpu_get_migratable_flags(FeatureWord w)
|
static uint64_t x86_cpu_get_migratable_flags(FeatureWord w)
|
||||||
{
|
{
|
||||||
FeatureWordInfo *wi = &feature_word_info[w];
|
FeatureWordInfo *wi = &feature_word_info[w];
|
||||||
uint32_t r = 0;
|
uint64_t r = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
uint32_t f = 1U << i;
|
uint64_t f = 1ULL << i;
|
||||||
|
|
||||||
/* If the feature name is known, it is implicitly considered migratable,
|
/* If the feature name is known, it is implicitly considered migratable,
|
||||||
* unless it is explicitly set in unmigratable_flags */
|
* unless it is explicitly set in unmigratable_flags */
|
||||||
|
@ -2931,7 +2931,7 @@ void x86_cpu_change_kvm_default(const char *prop, const char *value)
|
||||||
assert(pv->prop);
|
assert(pv->prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
||||||
bool migratable_only);
|
bool migratable_only);
|
||||||
|
|
||||||
static bool lmce_supported(void)
|
static bool lmce_supported(void)
|
||||||
|
@ -3117,7 +3117,7 @@ static bool x86_cpu_have_filtered_features(X86CPU *cpu)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint32_t mask,
|
static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint64_t mask,
|
||||||
const char *verbose_prefix)
|
const char *verbose_prefix)
|
||||||
{
|
{
|
||||||
CPUX86State *env = &cpu->env;
|
CPUX86State *env = &cpu->env;
|
||||||
|
@ -3134,8 +3134,8 @@ static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint32_t mask,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 32; ++i) {
|
for (i = 0; i < 64; ++i) {
|
||||||
if ((1UL << i) & mask) {
|
if ((1ULL << i) & mask) {
|
||||||
feat_word_str = feature_word_description(f, i);
|
feat_word_str = feature_word_description(f, i);
|
||||||
warn_report("%s: %s%s%s [bit %d]",
|
warn_report("%s: %s%s%s [bit %d]",
|
||||||
verbose_prefix,
|
verbose_prefix,
|
||||||
|
@ -3378,7 +3378,7 @@ static void x86_cpu_get_feature_words(Object *obj, Visitor *v,
|
||||||
const char *name, void *opaque,
|
const char *name, void *opaque,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
uint32_t *array = (uint32_t *)opaque;
|
uint64_t *array = (uint64_t *)opaque;
|
||||||
FeatureWord w;
|
FeatureWord w;
|
||||||
X86CPUFeatureWordInfo word_infos[FEATURE_WORDS] = { };
|
X86CPUFeatureWordInfo word_infos[FEATURE_WORDS] = { };
|
||||||
X86CPUFeatureWordInfoList list_entries[FEATURE_WORDS] = { };
|
X86CPUFeatureWordInfoList list_entries[FEATURE_WORDS] = { };
|
||||||
|
@ -3422,6 +3422,7 @@ static inline void feat2prop(char *s)
|
||||||
/* Return the feature property name for a feature flag bit */
|
/* Return the feature property name for a feature flag bit */
|
||||||
static const char *x86_cpu_feature_name(FeatureWord w, int bitnr)
|
static const char *x86_cpu_feature_name(FeatureWord w, int bitnr)
|
||||||
{
|
{
|
||||||
|
const char *name;
|
||||||
/* XSAVE components are automatically enabled by other features,
|
/* XSAVE components are automatically enabled by other features,
|
||||||
* so return the original feature name instead
|
* so return the original feature name instead
|
||||||
*/
|
*/
|
||||||
|
@ -3435,9 +3436,11 @@ static const char *x86_cpu_feature_name(FeatureWord w, int bitnr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(bitnr < 32);
|
assert(bitnr < 64);
|
||||||
assert(w < FEATURE_WORDS);
|
assert(w < FEATURE_WORDS);
|
||||||
return feature_word_info[w].feat_names[bitnr];
|
name = feature_word_info[w].feat_names[bitnr];
|
||||||
|
assert(bitnr < 32 || !(name && feature_word_info[w].type == CPUID_FEATURE_WORD));
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compatibily hack to maintain legacy +-feat semantic,
|
/* Compatibily hack to maintain legacy +-feat semantic,
|
||||||
|
@ -3553,10 +3556,10 @@ static void x86_cpu_list_feature_names(FeatureWordArray features,
|
||||||
strList **next = feat_names;
|
strList **next = feat_names;
|
||||||
|
|
||||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||||
uint32_t filtered = features[w];
|
uint64_t filtered = features[w];
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
if (filtered & (1UL << i)) {
|
if (filtered & (1ULL << i)) {
|
||||||
strList *new = g_new0(strList, 1);
|
strList *new = g_new0(strList, 1);
|
||||||
new->value = g_strdup(x86_cpu_feature_name(w, i));
|
new->value = g_strdup(x86_cpu_feature_name(w, i));
|
||||||
*next = new;
|
*next = new;
|
||||||
|
@ -3725,7 +3728,7 @@ void x86_cpu_list(void)
|
||||||
names = NULL;
|
names = NULL;
|
||||||
for (i = 0; i < ARRAY_SIZE(feature_word_info); i++) {
|
for (i = 0; i < ARRAY_SIZE(feature_word_info); i++) {
|
||||||
FeatureWordInfo *fw = &feature_word_info[i];
|
FeatureWordInfo *fw = &feature_word_info[i];
|
||||||
for (j = 0; j < 32; j++) {
|
for (j = 0; j < 64; j++) {
|
||||||
if (fw->feat_names[j]) {
|
if (fw->feat_names[j]) {
|
||||||
names = g_list_append(names, (gpointer)fw->feat_names[j]);
|
names = g_list_append(names, (gpointer)fw->feat_names[j]);
|
||||||
}
|
}
|
||||||
|
@ -3780,11 +3783,11 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
|
||||||
return cpu_list;
|
return cpu_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
||||||
bool migratable_only)
|
bool migratable_only)
|
||||||
{
|
{
|
||||||
FeatureWordInfo *wi = &feature_word_info[w];
|
FeatureWordInfo *wi = &feature_word_info[w];
|
||||||
uint32_t r = 0;
|
uint64_t r = 0;
|
||||||
|
|
||||||
if (kvm_enabled()) {
|
if (kvm_enabled()) {
|
||||||
switch (wi->type) {
|
switch (wi->type) {
|
||||||
|
@ -3955,7 +3958,7 @@ static QDict *x86_cpu_static_props(void)
|
||||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||||
FeatureWordInfo *fi = &feature_word_info[w];
|
FeatureWordInfo *fi = &feature_word_info[w];
|
||||||
int bit;
|
int bit;
|
||||||
for (bit = 0; bit < 32; bit++) {
|
for (bit = 0; bit < 64; bit++) {
|
||||||
if (!fi->feat_names[bit]) {
|
if (!fi->feat_names[bit]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -5111,7 +5114,7 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
|
||||||
for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) {
|
for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) {
|
||||||
FeatureDep *d = &feature_dependencies[i];
|
FeatureDep *d = &feature_dependencies[i];
|
||||||
if (!(env->features[d->from.index] & d->from.mask)) {
|
if (!(env->features[d->from.index] & d->from.mask)) {
|
||||||
uint32_t unavailable_features = env->features[d->to.index] & d->to.mask;
|
uint64_t unavailable_features = env->features[d->to.index] & d->to.mask;
|
||||||
|
|
||||||
/* Not an error unless the dependent feature was added explicitly. */
|
/* Not an error unless the dependent feature was added explicitly. */
|
||||||
mark_unavailable_features(cpu, d->to.index,
|
mark_unavailable_features(cpu, d->to.index,
|
||||||
|
@ -5206,10 +5209,10 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool verbose)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||||
uint32_t host_feat =
|
uint64_t host_feat =
|
||||||
x86_cpu_get_supported_feature_word(w, false);
|
x86_cpu_get_supported_feature_word(w, false);
|
||||||
uint32_t requested_features = env->features[w];
|
uint64_t requested_features = env->features[w];
|
||||||
uint32_t unavailable_features = requested_features & ~host_feat;
|
uint64_t unavailable_features = requested_features & ~host_feat;
|
||||||
mark_unavailable_features(cpu, w, unavailable_features, prefix);
|
mark_unavailable_features(cpu, w, unavailable_features, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5506,7 +5509,7 @@ static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp)
|
||||||
|
|
||||||
typedef struct BitProperty {
|
typedef struct BitProperty {
|
||||||
FeatureWord w;
|
FeatureWord w;
|
||||||
uint32_t mask;
|
uint64_t mask;
|
||||||
} BitProperty;
|
} BitProperty;
|
||||||
|
|
||||||
static void x86_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
|
static void x86_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
|
||||||
|
@ -5514,7 +5517,7 @@ static void x86_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
|
||||||
{
|
{
|
||||||
X86CPU *cpu = X86_CPU(obj);
|
X86CPU *cpu = X86_CPU(obj);
|
||||||
BitProperty *fp = opaque;
|
BitProperty *fp = opaque;
|
||||||
uint32_t f = cpu->env.features[fp->w];
|
uint64_t f = cpu->env.features[fp->w];
|
||||||
bool value = (f & fp->mask) == fp->mask;
|
bool value = (f & fp->mask) == fp->mask;
|
||||||
visit_type_bool(v, name, &value, errp);
|
visit_type_bool(v, name, &value, errp);
|
||||||
}
|
}
|
||||||
|
@ -5567,7 +5570,7 @@ static void x86_cpu_register_bit_prop(X86CPU *cpu,
|
||||||
{
|
{
|
||||||
BitProperty *fp;
|
BitProperty *fp;
|
||||||
ObjectProperty *op;
|
ObjectProperty *op;
|
||||||
uint32_t mask = (1UL << bitnr);
|
uint64_t mask = (1ULL << bitnr);
|
||||||
|
|
||||||
op = object_property_find(OBJECT(cpu), prop_name, NULL);
|
op = object_property_find(OBJECT(cpu), prop_name, NULL);
|
||||||
if (op) {
|
if (op) {
|
||||||
|
@ -5701,7 +5704,7 @@ static void x86_cpu_initfn(Object *obj)
|
||||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||||
int bitnr;
|
int bitnr;
|
||||||
|
|
||||||
for (bitnr = 0; bitnr < 32; bitnr++) {
|
for (bitnr = 0; bitnr < 64; bitnr++) {
|
||||||
x86_cpu_register_feature_bit_props(cpu, w, bitnr);
|
x86_cpu_register_feature_bit_props(cpu, w, bitnr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -502,7 +502,7 @@ typedef enum FeatureWord {
|
||||||
FEATURE_WORDS,
|
FEATURE_WORDS,
|
||||||
} FeatureWord;
|
} FeatureWord;
|
||||||
|
|
||||||
typedef uint32_t FeatureWordArray[FEATURE_WORDS];
|
typedef uint64_t FeatureWordArray[FEATURE_WORDS];
|
||||||
|
|
||||||
/* cpuid_features bits */
|
/* cpuid_features bits */
|
||||||
#define CPUID_FP87 (1U << 0)
|
#define CPUID_FP87 (1U << 0)
|
||||||
|
|
|
@ -442,7 +442,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index)
|
uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
struct kvm_msrs info;
|
struct kvm_msrs info;
|
||||||
|
|
Loading…
Reference in New Issue