s390x/cpumodel: implement QMP interface "query-cpu-model-comparison"

Let's implement that interface by reusing our convertion code implemented
for expansion.

We use CPU generations and CPU features to calculate the result. This
means, that a zEC12 cannot simply be converted into a z13 by stripping
of features. This is required, as other magic values (e.g. maximum
address sizes) belong to a CPU generation and cannot simply be
emulated by an older generation.

Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Message-Id: <20160905085244.99980-30-dahi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
This commit is contained in:
David Hildenbrand 2016-09-05 10:52:43 +02:00 committed by Cornelia Huck
parent 137974cea3
commit 4e82ef0502
2 changed files with 86 additions and 1 deletions

View File

@ -3232,7 +3232,8 @@
# global properties may affect expansion of CPU models. Using
# query-cpu-model-expansion while using these is not advised.
#
# Some architectures may not support comparing CPU models.
# Some architectures may not support comparing CPU models. s390x supports
# comparing CPU models.
#
# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is
# not supported, if a model cannot be used, if a model contains

View File

@ -450,6 +450,90 @@ CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type
cpu_info_from_model(expansion_info->model, &s390_model, delta_changes);
return expansion_info;
}
static void list_add_feat(const char *name, void *opaque)
{
strList **last = (strList **) opaque;
strList *entry;
entry = g_malloc0(sizeof(*entry));
entry->value = g_strdup(name);
entry->next = *last;
*last = entry;
}
CpuModelCompareInfo *arch_query_cpu_model_comparison(CpuModelInfo *infoa,
CpuModelInfo *infob,
Error **errp)
{
CpuModelCompareResult feat_result, gen_result;
CpuModelCompareInfo *compare_info;
S390FeatBitmap missing, added;
S390CPUModel modela, modelb;
/* convert both models to our internal representation */
cpu_model_from_info(&modela, infoa, errp);
if (*errp) {
return NULL;
}
cpu_model_from_info(&modelb, infob, errp);
if (*errp) {
return NULL;
}
compare_info = g_malloc0(sizeof(*compare_info));
/* check the cpu generation and ga level */
if (modela.def->gen == modelb.def->gen) {
if (modela.def->ec_ga == modelb.def->ec_ga) {
/* ec and corresponding bc are identical */
gen_result = CPU_MODEL_COMPARE_RESULT_IDENTICAL;
} else if (modela.def->ec_ga < modelb.def->ec_ga) {
gen_result = CPU_MODEL_COMPARE_RESULT_SUBSET;
} else {
gen_result = CPU_MODEL_COMPARE_RESULT_SUPERSET;
}
} else if (modela.def->gen < modelb.def->gen) {
gen_result = CPU_MODEL_COMPARE_RESULT_SUBSET;
} else {
gen_result = CPU_MODEL_COMPARE_RESULT_SUPERSET;
}
if (gen_result != CPU_MODEL_COMPARE_RESULT_IDENTICAL) {
/* both models cannot be made identical */
list_add_feat("type", &compare_info->responsible_properties);
}
/* check the feature set */
if (bitmap_equal(modela.features, modelb.features, S390_FEAT_MAX)) {
feat_result = CPU_MODEL_COMPARE_RESULT_IDENTICAL;
} else {
bitmap_andnot(missing, modela.features, modelb.features, S390_FEAT_MAX);
s390_feat_bitmap_to_ascii(missing,
&compare_info->responsible_properties,
list_add_feat);
bitmap_andnot(added, modelb.features, modela.features, S390_FEAT_MAX);
s390_feat_bitmap_to_ascii(added, &compare_info->responsible_properties,
list_add_feat);
if (bitmap_empty(missing, S390_FEAT_MAX)) {
feat_result = CPU_MODEL_COMPARE_RESULT_SUBSET;
} else if (bitmap_empty(added, S390_FEAT_MAX)) {
feat_result = CPU_MODEL_COMPARE_RESULT_SUPERSET;
} else {
feat_result = CPU_MODEL_COMPARE_RESULT_INCOMPATIBLE;
}
}
/* combine the results */
if (gen_result == feat_result) {
compare_info->result = gen_result;
} else if (feat_result == CPU_MODEL_COMPARE_RESULT_IDENTICAL) {
compare_info->result = gen_result;
} else if (gen_result == CPU_MODEL_COMPARE_RESULT_IDENTICAL) {
compare_info->result = feat_result;
} else {
compare_info->result = CPU_MODEL_COMPARE_RESULT_INCOMPATIBLE;
}
return compare_info;
}
#endif
static void check_consistency(const S390CPUModel *model)