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:
parent
137974cea3
commit
4e82ef0502
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user