i386: Reorganize and document CPUID initialization steps
CPU runnability checks and CPU model expansion have slightly different requirements. Document the steps involved in loading a CPU model and realizing a CPU, so their requirements and purpose are clearly defined. This patch doesn't change any implementation. It just add comments, rename the x86_cpu_load_features() function for clarity (so it won't be confused with x86_cpu_load_def()), and move x86_cpu_filter_features() closer to it. Message-Id: <20170116211124.29245-2-ehabkost@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
parent
44bd8e5306
commit
b8d834a00f
@ -2059,7 +2059,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
|
||||
@ -2082,9 +2082,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.
|
||||
*/
|
||||
@ -2245,31 +2245,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;
|
||||
@ -3093,8 +3068,47 @@ 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;
|
||||
@ -3171,6 +3185,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)
|
||||
@ -3198,7 +3238,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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user