static void check_compatibility(const S390CPUModel *max_model, const S390CPUModel *model, Error **errp) { S390FeatBitmap missing; if (model->def->gen > max_model->def->gen) { error_setg(errp, "Selected CPU generation is too new. Maximum " "supported model in the configuration: \'%s\'", max_model->def->name); return; } else if (model->def->gen == max_model->def->gen && model->def->ec_ga > max_model->def->ec_ga) { error_setg(errp, "Selected CPU GA level is too new. Maximum " "supported model in the configuration: \'%s\'", max_model->def->name); return; } /* detect the missing features to properly report them */ bitmap_andnot(missing, model->features, max_model->features, S390_FEAT_MAX); if (bitmap_empty(missing, S390_FEAT_MAX)) { return; } error_setg(errp, " "); s390_feat_bitmap_to_ascii(missing, errp, error_prepend_missing_feat); error_prepend(errp, "Some features requested in the CPU model are not " "available in the configuration: "); }
/* convert S390CPUDef into a static CpuModelInfo */ static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model, bool delta_changes) { QDict *qdict = qdict_new(); S390FeatBitmap bitmap; /* always fallback to the static base model */ info->name = g_strdup_printf("%s-base", model->def->name); if (delta_changes) { /* features deleted from the base feature set */ bitmap_andnot(bitmap, model->def->base_feat, model->features, S390_FEAT_MAX); if (!bitmap_empty(bitmap, S390_FEAT_MAX)) { s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_disabled_feat); } /* features added to the base feature set */ bitmap_andnot(bitmap, model->features, model->def->base_feat, S390_FEAT_MAX); if (!bitmap_empty(bitmap, S390_FEAT_MAX)) { s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_enabled_feat); } } else { /* expand all features */ s390_feat_bitmap_to_ascii(model->features, qdict, qdict_add_enabled_feat); bitmap_complement(bitmap, model->features, S390_FEAT_MAX); s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_disabled_feat); } if (!qdict_size(qdict)) { QDECREF(qdict); } else { info->props = QOBJECT(qdict); info->has_props = true; } }
static void check_unavailable_features(const S390CPUModel *max_model, const S390CPUModel *model, strList **unavailable) { S390FeatBitmap missing; /* check general model compatibility */ if (max_model->def->gen < model->def->gen || (max_model->def->gen == model->def->gen && max_model->def->ec_ga < model->def->ec_ga)) { list_add_feat("type", unavailable); } /* detect missing features if any to properly report them */ bitmap_andnot(missing, model->features, max_model->features, S390_FEAT_MAX); if (!bitmap_empty(missing, S390_FEAT_MAX)) { s390_feat_bitmap_to_ascii(missing, unavailable, list_add_feat); } }
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; }