x86 queue, 2017-02-27

"-cpu max" and query-cpu-model-expansion support for x86. This
 should be the last x86 pull request before 2.9 soft freeze.
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABCAAGBQJYtFKvAAoJECgHk2+YTcWmyCwQAJEBM8NdOmN14yA3qTiTs0Kd
 D/3VWSxtu9t41g39+yho70c+ZnpqGW28/WbY7E4ovAPRIoUI/pmKACY42k+WrTmK
 MIBMesp1YnkxhwrFW9CwgqiUV8nr5ZMlzW/pQU/GaXbcH+7KfObeI93iGhtGjWvi
 4nNvrK7b5mz2wPU6s1j+Bz2mp0CMd/sktmiH93tyWU+KgU7NXvMDPInVkfvBMvZN
 5D6JLIeKxrndbaaUgvGbR4SUUmRs8TZFYfEbOdkkjIqh7MAKVKCCipFaxWIEfndr
 bs1MDmw6uIUaI55JuWaXb//BkS+jai1dmn+ZEzMoisetlheSwR8cEStFJBxcm/7n
 WQfxUd6TuNJ9PC1FIvb/OHUCGvzb+vtbEYAMmvCv8BVMnMivN7WNliu3rNVRgWBK
 OHClBPdgwoIx2cGt6ic1rvxHxcpjeJ/YXBzL/JbBkblckpxbNRcW1NRTZKHIe3vr
 JcPMEoP8g5d9ZHOG0WqBhKtJ3vUrxF3xqBKuR1Ha7QWpyKe9YF+RKrIA9dZkhLy0
 Jh0fPZn2PmQrbLuZTC1u7Sgp22Duy7RcfJ7SikR+uhMLtkvToqu3ywLteW6Ta1by
 oinb2UYMazwpAKKDcab4GdNJHPOuhnDw58osBVTyBiiN1tJjH+BhnVV4bYJVpaHI
 MJIx5QvwqocSO0qoDZxo
 =KPbC
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging

x86 queue, 2017-02-27

"-cpu max" and query-cpu-model-expansion support for x86. This
should be the last x86 pull request before 2.9 soft freeze.

# gpg: Signature made Mon 27 Feb 2017 16:24:15 GMT
# gpg:                using RSA key 0x2807936F984DC5A6
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>"
# Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF  D1AA 2807 936F 984D C5A6

* remotes/ehabkost/tags/x86-pull-request:
  i386: Improve query-cpu-model-expansion full mode
  i386: Implement query-cpu-model-expansion QMP command
  i386: Define static "base" CPU model
  i386: Don't set CPUClass::cpu_def on "max" model
  i386: Make "max" model not use any host CPUID info on TCG
  i386: Create "max" CPU model
  qapi-schema: Comment about full expansion of non-migration-safe models
  i386: Reorganize and document CPUID initialization steps
  i386: Rename X86CPU::host_features to X86CPU::max_features
  i386: Add ordering field to CPUClass
  i386: Unset cannot_destroy_with_object_finalize_yet on "host" model

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2017-03-02 11:18:01 +00:00
commit 666095c852
5 changed files with 397 additions and 81 deletions

View File

@ -984,8 +984,10 @@ static void qmp_unregister_commands_hack(void)
#ifndef TARGET_ARM
qmp_unregister_command("query-gic-capabilities");
#endif
#if !defined(TARGET_S390X)
#if !defined(TARGET_S390X) && !defined(TARGET_I386)
qmp_unregister_command("query-cpu-model-expansion");
#endif
#if !defined(TARGET_S390X)
qmp_unregister_command("query-cpu-model-baseline");
qmp_unregister_command("query-cpu-model-comparison");
#endif

View File

@ -4274,6 +4274,15 @@
# migration-safe, but allows tooling to get an insight and work with
# model details.
#
# Note: When a non-migration-safe CPU model is expanded in static mode, some
# features enabled by the CPU model may be omitted, because they can't be
# implemented by a static CPU model definition (e.g. cache info passthrough and
# PMU passthrough in x86). If you need an accurate representation of the
# features enabled by a non-migration-safe CPU model, use @full. If you need a
# static representation that will keep ABI compatibility even when changing QEMU
# version or machine-type, use @static (but keep in mind that some features may
# be omitted).
#
# Since: 2.8.0
##
{ 'enum': 'CpuModelExpansionType',

View File

@ -48,7 +48,9 @@ typedef struct X86CPUDefinition X86CPUDefinition;
* X86CPUClass:
* @cpu_def: CPU model definition
* @kvm_required: Whether CPU model requires KVM to be enabled.
* @ordering: Ordering on the "-cpu help" CPU model list.
* @migration_safe: See CpuDefinitionInfo::migration_safe
* @static_model: See CpuDefinitionInfo::static
* @parent_realize: The parent class' realize handler.
* @parent_reset: The parent class' reset handler.
*
@ -59,11 +61,15 @@ typedef struct X86CPUClass {
CPUClass parent_class;
/*< public >*/
/* Should be eventually replaced by subclass-specific property defaults. */
/* CPU definition, automatically loaded by instance_init if not NULL.
* Should be eventually replaced by subclass-specific property defaults.
*/
X86CPUDefinition *cpu_def;
bool kvm_required;
int ordering;
bool migration_safe;
bool static_model;
/* Optional description of CPU model.
* If unavailable, cpu_def->model_id is used */

View File

@ -29,10 +29,16 @@
#include "qemu/option.h"
#include "qemu/config-file.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qmp/qstring.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qbool.h"
#include "qapi/qmp/qint.h"
#include "qapi/qmp/qfloat.h"
#include "qapi-types.h"
#include "qapi-visit.h"
#include "qapi/visitor.h"
#include "qom/qom-qobject.h"
#include "sysemu/arch_init.h"
#if defined(CONFIG_KVM)
@ -1503,15 +1509,15 @@ void x86_cpu_change_kvm_default(const char *prop, const char *value)
static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
bool migratable_only);
#ifdef CONFIG_KVM
static bool lmce_supported(void)
{
uint64_t mce_cap;
uint64_t mce_cap = 0;
#ifdef CONFIG_KVM
if (kvm_ioctl(kvm_state, KVM_X86_GET_MCE_CAP_SUPPORTED, &mce_cap) < 0) {
return false;
}
#endif
return !!(mce_cap & MCG_LMCE_P);
}
@ -1531,51 +1537,28 @@ static int cpu_x86_fill_model_id(char *str)
return 0;
}
static X86CPUDefinition host_cpudef;
static Property host_x86_cpu_properties[] = {
static Property max_x86_cpu_properties[] = {
DEFINE_PROP_BOOL("migratable", X86CPU, migratable, true),
DEFINE_PROP_BOOL("host-cache-info", X86CPU, cache_info_passthrough, false),
DEFINE_PROP_END_OF_LIST()
};
/* class_init for the "host" CPU model
*
* This function may be called before KVM is initialized.
*/
static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
static void max_x86_cpu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
X86CPUClass *xcc = X86_CPU_CLASS(oc);
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
xcc->kvm_required = true;
xcc->ordering = 9;
host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
x86_cpu_vendor_words2str(host_cpudef.vendor, ebx, edx, ecx);
host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
host_cpudef.family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
host_cpudef.model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
host_cpudef.stepping = eax & 0x0F;
cpu_x86_fill_model_id(host_cpudef.model_id);
xcc->cpu_def = &host_cpudef;
xcc->model_description =
"KVM processor with all supported host features "
"(only available in KVM mode)";
"Enables all features supported by the accelerator in the current host";
/* level, xlevel, xlevel2, and the feature words are initialized on
* instance_init, because they require KVM to be initialized.
*/
dc->props = host_x86_cpu_properties;
/* Reason: host_x86_cpu_initfn() dies when !kvm_enabled() */
dc->cannot_destroy_with_object_finalize_yet = true;
dc->props = max_x86_cpu_properties;
}
static void host_x86_cpu_initfn(Object *obj)
static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp);
static void max_x86_cpu_initfn(Object *obj)
{
X86CPU *cpu = X86_CPU(obj);
CPUX86State *env = &cpu->env;
@ -1584,10 +1567,24 @@ static void host_x86_cpu_initfn(Object *obj)
/* We can't fill the features array here because we don't know yet if
* "migratable" is true or false.
*/
cpu->host_features = true;
cpu->max_features = true;
/* If KVM is disabled, x86_cpu_realizefn() will report an error later */
if (kvm_enabled()) {
X86CPUDefinition host_cpudef = { };
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
x86_cpu_vendor_words2str(host_cpudef.vendor, ebx, edx, ecx);
host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
host_cpudef.family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
host_cpudef.model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
host_cpudef.stepping = eax & 0x0F;
cpu_x86_fill_model_id(host_cpudef.model_id);
x86_cpu_load_def(cpu, &host_cpudef, &error_abort);
env->cpuid_min_level =
kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
env->cpuid_min_xlevel =
@ -1598,15 +1595,44 @@ static void host_x86_cpu_initfn(Object *obj)
if (lmce_supported()) {
object_property_set_bool(OBJECT(cpu), true, "lmce", &error_abort);
}
} else {
object_property_set_str(OBJECT(cpu), CPUID_VENDOR_AMD,
"vendor", &error_abort);
object_property_set_int(OBJECT(cpu), 6, "family", &error_abort);
object_property_set_int(OBJECT(cpu), 6, "model", &error_abort);
object_property_set_int(OBJECT(cpu), 3, "stepping", &error_abort);
object_property_set_str(OBJECT(cpu),
"QEMU TCG CPU version " QEMU_HW_VERSION,
"model-id", &error_abort);
}
object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort);
}
static const TypeInfo max_x86_cpu_type_info = {
.name = X86_CPU_TYPE_NAME("max"),
.parent = TYPE_X86_CPU,
.instance_init = max_x86_cpu_initfn,
.class_init = max_x86_cpu_class_init,
};
#ifdef CONFIG_KVM
static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
{
X86CPUClass *xcc = X86_CPU_CLASS(oc);
xcc->kvm_required = true;
xcc->ordering = 8;
xcc->model_description =
"KVM processor with all supported host features "
"(only available in KVM mode)";
}
static const TypeInfo host_x86_cpu_type_info = {
.name = X86_CPU_TYPE_NAME("host"),
.parent = TYPE_X86_CPU,
.instance_init = host_x86_cpu_initfn,
.parent = X86_CPU_TYPE_NAME("max"),
.class_init = host_x86_cpu_class_init,
};
@ -2060,7 +2086,7 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features,
}
}
static void x86_cpu_load_features(X86CPU *cpu, Error **errp);
static void x86_cpu_expand_features(X86CPU *cpu, Error **errp);
static int x86_cpu_filter_features(X86CPU *cpu);
/* Check for missing features that may prevent the CPU class from
@ -2083,9 +2109,9 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc,
xc = X86_CPU(object_new(object_class_get_name(OBJECT_CLASS(xcc))));
x86_cpu_load_features(xc, &err);
x86_cpu_expand_features(xc, &err);
if (err) {
/* Errors at x86_cpu_load_features should never happen,
/* Errors at x86_cpu_expand_features should never happen,
* but in case it does, just report the model as not
* runnable at all using the "type" property.
*/
@ -2128,7 +2154,7 @@ static void listflags(FILE *f, fprintf_function print, const char **featureset)
}
}
/* Sort alphabetically by type name, listing kvm_required models last. */
/* Sort alphabetically by type name, respecting X86CPUClass::ordering. */
static gint x86_cpu_list_compare(gconstpointer a, gconstpointer b)
{
ObjectClass *class_a = (ObjectClass *)a;
@ -2137,9 +2163,8 @@ static gint x86_cpu_list_compare(gconstpointer a, gconstpointer b)
X86CPUClass *cc_b = X86_CPU_CLASS(class_b);
const char *name_a, *name_b;
if (cc_a->kvm_required != cc_b->kvm_required) {
/* kvm_required items go last */
return cc_a->kvm_required ? 1 : -1;
if (cc_a->ordering != cc_b->ordering) {
return cc_a->ordering - cc_b->ordering;
} else {
name_a = object_class_get_name(class_a);
name_b = object_class_get_name(class_b);
@ -2161,7 +2186,7 @@ static void x86_cpu_list_entry(gpointer data, gpointer user_data)
CPUListState *s = user_data;
char *name = x86_cpu_class_get_model_name(cc);
const char *desc = cc->model_description;
if (!desc) {
if (!desc && cc->cpu_def) {
desc = cc->cpu_def->model_id;
}
@ -2210,6 +2235,7 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data)
info->q_typename = g_strdup(object_class_get_name(oc));
info->migration_safe = cc->migration_safe;
info->has_migration_safe = true;
info->q_static = cc->static_model;
entry = g_malloc0(sizeof(*entry));
entry->value = info;
@ -2247,31 +2273,6 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
return r;
}
/*
* Filters CPU feature words based on host availability of each feature.
*
* Returns: 0 if all flags are supported by the host, non-zero otherwise.
*/
static int x86_cpu_filter_features(X86CPU *cpu)
{
CPUX86State *env = &cpu->env;
FeatureWord w;
int rv = 0;
for (w = 0; w < FEATURE_WORDS; w++) {
uint32_t host_feat =
x86_cpu_get_supported_feature_word(w, false);
uint32_t requested_features = env->features[w];
env->features[w] &= host_feat;
cpu->filtered_features[w] = requested_features & ~env->features[w];
if (cpu->filtered_features[w]) {
rv = 1;
}
}
return rv;
}
static void x86_cpu_report_filtered_features(X86CPU *cpu)
{
FeatureWord w;
@ -2293,7 +2294,7 @@ static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props)
}
}
/* Load data from X86CPUDefinition
/* Load data from X86CPUDefinition into a X86CPU object
*/
static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
{
@ -2302,6 +2303,11 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
char host_vendor[CPUID_VENDOR_SZ + 1];
FeatureWord w;
/*NOTE: any property set by this function should be returned by
* x86_cpu_static_props(), so static expansion of
* query-cpu-model-expansion is always complete.
*/
/* CPU models only set _minimum_ values for level/xlevel: */
object_property_set_int(OBJECT(cpu), def->level, "min-level", errp);
object_property_set_int(OBJECT(cpu), def->xlevel, "min-xlevel", errp);
@ -2346,6 +2352,212 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
}
/* Return a QDict containing keys for all properties that can be included
* in static expansion of CPU models. All properties set by x86_cpu_load_def()
* must be included in the dictionary.
*/
static QDict *x86_cpu_static_props(void)
{
FeatureWord w;
int i;
static const char *props[] = {
"min-level",
"min-xlevel",
"family",
"model",
"stepping",
"model-id",
"vendor",
"lmce",
NULL,
};
static QDict *d;
if (d) {
return d;
}
d = qdict_new();
for (i = 0; props[i]; i++) {
qdict_put_obj(d, props[i], qnull());
}
for (w = 0; w < FEATURE_WORDS; w++) {
FeatureWordInfo *fi = &feature_word_info[w];
int bit;
for (bit = 0; bit < 32; bit++) {
if (!fi->feat_names[bit]) {
continue;
}
qdict_put_obj(d, fi->feat_names[bit], qnull());
}
}
return d;
}
/* Add an entry to @props dict, with the value for property. */
static void x86_cpu_expand_prop(X86CPU *cpu, QDict *props, const char *prop)
{
QObject *value = object_property_get_qobject(OBJECT(cpu), prop,
&error_abort);
qdict_put_obj(props, prop, value);
}
/* Convert CPU model data from X86CPU object to a property dictionary
* that can recreate exactly the same CPU model.
*/
static void x86_cpu_to_dict(X86CPU *cpu, QDict *props)
{
QDict *sprops = x86_cpu_static_props();
const QDictEntry *e;
for (e = qdict_first(sprops); e; e = qdict_next(sprops, e)) {
const char *prop = qdict_entry_key(e);
x86_cpu_expand_prop(cpu, props, prop);
}
}
/* Convert CPU model data from X86CPU object to a property dictionary
* that can recreate exactly the same CPU model, including every
* writeable QOM property.
*/
static void x86_cpu_to_dict_full(X86CPU *cpu, QDict *props)
{
ObjectPropertyIterator iter;
ObjectProperty *prop;
object_property_iter_init(&iter, OBJECT(cpu));
while ((prop = object_property_iter_next(&iter))) {
/* skip read-only or write-only properties */
if (!prop->get || !prop->set) {
continue;
}
/* "hotplugged" is the only property that is configurable
* on the command-line but will be set differently on CPUs
* created using "-cpu ... -smp ..." and by CPUs created
* on the fly by x86_cpu_from_model() for querying. Skip it.
*/
if (!strcmp(prop->name, "hotplugged")) {
continue;
}
x86_cpu_expand_prop(cpu, props, prop->name);
}
}
static void object_apply_props(Object *obj, QDict *props, Error **errp)
{
const QDictEntry *prop;
Error *err = NULL;
for (prop = qdict_first(props); prop; prop = qdict_next(props, prop)) {
object_property_set_qobject(obj, qdict_entry_value(prop),
qdict_entry_key(prop), &err);
if (err) {
break;
}
}
error_propagate(errp, err);
}
/* Create X86CPU object according to model+props specification */
static X86CPU *x86_cpu_from_model(const char *model, QDict *props, Error **errp)
{
X86CPU *xc = NULL;
X86CPUClass *xcc;
Error *err = NULL;
xcc = X86_CPU_CLASS(cpu_class_by_name(TYPE_X86_CPU, model));
if (xcc == NULL) {
error_setg(&err, "CPU model '%s' not found", model);
goto out;
}
xc = X86_CPU(object_new(object_class_get_name(OBJECT_CLASS(xcc))));
if (props) {
object_apply_props(OBJECT(xc), props, &err);
if (err) {
goto out;
}
}
x86_cpu_expand_features(xc, &err);
if (err) {
goto out;
}
out:
if (err) {
error_propagate(errp, err);
object_unref(OBJECT(xc));
xc = NULL;
}
return xc;
}
CpuModelExpansionInfo *
arch_query_cpu_model_expansion(CpuModelExpansionType type,
CpuModelInfo *model,
Error **errp)
{
X86CPU *xc = NULL;
Error *err = NULL;
CpuModelExpansionInfo *ret = g_new0(CpuModelExpansionInfo, 1);
QDict *props = NULL;
const char *base_name;
xc = x86_cpu_from_model(model->name,
model->has_props ?
qobject_to_qdict(model->props) :
NULL, &err);
if (err) {
goto out;
}
props = qdict_new();
switch (type) {
case CPU_MODEL_EXPANSION_TYPE_STATIC:
/* Static expansion will be based on "base" only */
base_name = "base";
x86_cpu_to_dict(xc, props);
break;
case CPU_MODEL_EXPANSION_TYPE_FULL:
/* As we don't return every single property, full expansion needs
* to keep the original model name+props, and add extra
* properties on top of that.
*/
base_name = model->name;
x86_cpu_to_dict_full(xc, props);
break;
default:
error_setg(&err, "Unsupportted expansion type");
goto out;
}
if (!props) {
props = qdict_new();
}
x86_cpu_to_dict(xc, props);
ret->model = g_new0(CpuModelInfo, 1);
ret->model->name = g_strdup(base_name);
ret->model->props = QOBJECT(props);
ret->model->has_props = true;
out:
object_unref(OBJECT(xc));
if (err) {
error_propagate(errp, err);
qapi_free_CpuModelExpansionInfo(ret);
ret = NULL;
}
return ret;
}
X86CPU *cpu_x86_init(const char *cpu_model)
{
return X86_CPU(cpu_generic_init(TYPE_X86_CPU, cpu_model));
@ -3095,20 +3307,59 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
env->features[FEAT_XSAVE_COMP_HI] = mask >> 32;
}
/* Load CPUID data based on configured features */
static void x86_cpu_load_features(X86CPU *cpu, Error **errp)
/***** Steps involved on loading and filtering CPUID data
*
* When initializing and realizing a CPU object, the steps
* involved in setting up CPUID data are:
*
* 1) Loading CPU model definition (X86CPUDefinition). This is
* implemented by x86_cpu_load_def() and should be completely
* transparent, as it is done automatically by instance_init.
* No code should need to look at X86CPUDefinition structs
* outside instance_init.
*
* 2) CPU expansion. This is done by realize before CPUID
* filtering, and will make sure host/accelerator data is
* loaded for CPU models that depend on host capabilities
* (e.g. "host"). Done by x86_cpu_expand_features().
*
* 3) CPUID filtering. This initializes extra data related to
* CPUID, and checks if the host supports all capabilities
* required by the CPU. Runnability of a CPU model is
* determined at this step. Done by x86_cpu_filter_features().
*
* Some operations don't require all steps to be performed.
* More precisely:
*
* - CPU instance creation (instance_init) will run only CPU
* model loading. CPU expansion can't run at instance_init-time
* because host/accelerator data may be not available yet.
* - CPU realization will perform both CPU model expansion and CPUID
* filtering, and return an error in case one of them fails.
* - query-cpu-definitions needs to run all 3 steps. It needs
* to run CPUID filtering, as the 'unavailable-features'
* field is set based on the filtering results.
* - The query-cpu-model-expansion QMP command only needs to run
* CPU model loading and CPU expansion. It should not filter
* any CPUID data based on host capabilities.
*/
/* Expand CPU configuration data, based on configured features
* and host/accelerator capabilities when appropriate.
*/
static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
{
CPUX86State *env = &cpu->env;
FeatureWord w;
GList *l;
Error *local_err = NULL;
/*TODO: cpu->host_features incorrectly overwrites features
/*TODO: cpu->max_features incorrectly overwrites features
* set using "feat=on|off". Once we fix this, we can convert
* plus_features & minus_features to global properties
* inside x86_cpu_parse_featurestr() too.
*/
if (cpu->host_features) {
if (cpu->max_features) {
for (w = 0; w < FEATURE_WORDS; w++) {
env->features[w] =
x86_cpu_get_supported_feature_word(w, cpu->migratable);
@ -3173,6 +3424,32 @@ out:
}
}
/*
* Finishes initialization of CPUID data, filters CPU feature
* words based on host availability of each feature.
*
* Returns: 0 if all flags are supported by the host, non-zero otherwise.
*/
static int x86_cpu_filter_features(X86CPU *cpu)
{
CPUX86State *env = &cpu->env;
FeatureWord w;
int rv = 0;
for (w = 0; w < FEATURE_WORDS; w++) {
uint32_t host_feat =
x86_cpu_get_supported_feature_word(w, false);
uint32_t requested_features = env->features[w];
env->features[w] &= host_feat;
cpu->filtered_features[w] = requested_features & ~env->features[w];
if (cpu->filtered_features[w]) {
rv = 1;
}
}
return rv;
}
#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \
(env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \
(env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3)
@ -3200,7 +3477,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
return;
}
x86_cpu_load_features(cpu, &local_err);
x86_cpu_expand_features(cpu, &local_err);
if (local_err) {
goto out;
}
@ -3619,7 +3896,9 @@ static void x86_cpu_initfn(Object *obj)
object_property_add_alias(obj, "sse4_1", obj, "sse4.1", &error_abort);
object_property_add_alias(obj, "sse4_2", obj, "sse4.2", &error_abort);
x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort);
if (xcc->cpu_def) {
x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort);
}
}
static int64_t x86_cpu_get_arch_id(CPUState *cs)
@ -3774,6 +4053,24 @@ static const TypeInfo x86_cpu_type_info = {
.class_init = x86_cpu_common_class_init,
};
/* "base" CPU model, used by query-cpu-model-expansion */
static void x86_cpu_base_class_init(ObjectClass *oc, void *data)
{
X86CPUClass *xcc = X86_CPU_CLASS(oc);
xcc->static_model = true;
xcc->migration_safe = true;
xcc->model_description = "base CPU model type with no features enabled";
xcc->ordering = 8;
}
static const TypeInfo x86_base_cpu_type_info = {
.name = X86_CPU_TYPE_NAME("base"),
.parent = TYPE_X86_CPU,
.class_init = x86_cpu_base_class_init,
};
static void x86_cpu_register_types(void)
{
int i;
@ -3782,6 +4079,8 @@ static void x86_cpu_register_types(void)
for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
x86_register_cpudef_type(&builtin_x86_defs[i]);
}
type_register_static(&max_x86_cpu_type_info);
type_register_static(&x86_base_cpu_type_info);
#ifdef CONFIG_KVM
type_register_static(&host_x86_cpu_type_info);
#endif

View File

@ -1211,7 +1211,7 @@ struct X86CPU {
bool enforce_cpuid;
bool expose_kvm;
bool migratable;
bool host_features;
bool max_features; /* Enable all supported features automatically */
uint32_t apic_id;
/* Enables publishing of TSC increment and Local APIC bus frequencies to