qemu/target/s390x/cpu_models.c
<<
>>
Prefs
   1/*
   2 * CPU models for s390x
   3 *
   4 * Copyright 2016 IBM Corp.
   5 *
   6 * Author(s): David Hildenbrand <dahi@linux.vnet.ibm.com>
   7 *
   8 * This work is licensed under the terms of the GNU GPL, version 2 or (at
   9 * your option) any later version. See the COPYING file in the top-level
  10 * directory.
  11 */
  12
  13#include "qemu/osdep.h"
  14#include "cpu.h"
  15#include "gen-features.h"
  16#include "qapi/error.h"
  17#include "qapi/visitor.h"
  18#include "qemu/error-report.h"
  19#include "qapi/qmp/qerror.h"
  20#include "qapi/qobject-input-visitor.h"
  21#include "qapi/qmp/qbool.h"
  22#ifndef CONFIG_USER_ONLY
  23#include "sysemu/arch_init.h"
  24#endif
  25
  26#define CPUDEF_INIT(_type, _gen, _ec_ga, _mha_pow, _hmfai, _name, _desc) \
  27    {                                                                    \
  28        .name = _name,                                                   \
  29        .type = _type,                                                   \
  30        .gen = _gen,                                                     \
  31        .ec_ga = _ec_ga,                                                 \
  32        .mha_pow = _mha_pow,                                             \
  33        .hmfai = _hmfai,                                                 \
  34        .desc = _desc,                                                   \
  35        .base_init = { S390_FEAT_LIST_GEN ## _gen ## _GA ## _ec_ga ## _BASE },  \
  36        .default_init = { S390_FEAT_LIST_GEN ## _gen ## _GA ## _ec_ga ## _DEFAULT },  \
  37        .full_init = { S390_FEAT_LIST_GEN ## _gen ## _GA ## _ec_ga ## _FULL },  \
  38    }
  39
  40/*
  41 * CPU definiton list in order of release. For now, base features of a
  42 * following release are always a subset of base features of the previous
  43 * release. Same is correct for the other feature sets.
  44 * A BC release always follows the corresponding EC release.
  45 */
  46static S390CPUDef s390_cpu_defs[] = {
  47    CPUDEF_INIT(0x2064, 7, 1, 38, 0x00000000U, "z900", "IBM zSeries 900 GA1"),
  48    CPUDEF_INIT(0x2064, 7, 2, 38, 0x00000000U, "z900.2", "IBM zSeries 900 GA2"),
  49    CPUDEF_INIT(0x2064, 7, 3, 38, 0x00000000U, "z900.3", "IBM zSeries 900 GA3"),
  50    CPUDEF_INIT(0x2066, 7, 3, 38, 0x00000000U, "z800", "IBM zSeries 800 GA1"),
  51    CPUDEF_INIT(0x2084, 8, 1, 38, 0x00000000U, "z990", "IBM zSeries 990 GA1"),
  52    CPUDEF_INIT(0x2084, 8, 2, 38, 0x00000000U, "z990.2", "IBM zSeries 990 GA2"),
  53    CPUDEF_INIT(0x2084, 8, 3, 38, 0x00000000U, "z990.3", "IBM zSeries 990 GA3"),
  54    CPUDEF_INIT(0x2086, 8, 3, 38, 0x00000000U, "z890", "IBM zSeries 880 GA1"),
  55    CPUDEF_INIT(0x2084, 8, 4, 38, 0x00000000U, "z990.4", "IBM zSeries 990 GA4"),
  56    CPUDEF_INIT(0x2086, 8, 4, 38, 0x00000000U, "z890.2", "IBM zSeries 880 GA2"),
  57    CPUDEF_INIT(0x2084, 8, 5, 38, 0x00000000U, "z990.5", "IBM zSeries 990 GA5"),
  58    CPUDEF_INIT(0x2086, 8, 5, 38, 0x00000000U, "z890.3", "IBM zSeries 880 GA3"),
  59    CPUDEF_INIT(0x2094, 9, 1, 40, 0x00000000U, "z9EC", "IBM System z9 EC GA1"),
  60    CPUDEF_INIT(0x2094, 9, 2, 40, 0x00000000U, "z9EC.2", "IBM System z9 EC GA2"),
  61    CPUDEF_INIT(0x2096, 9, 2, 40, 0x00000000U, "z9BC", "IBM System z9 BC GA1"),
  62    CPUDEF_INIT(0x2094, 9, 3, 40, 0x00000000U, "z9EC.3", "IBM System z9 EC GA3"),
  63    CPUDEF_INIT(0x2096, 9, 3, 40, 0x00000000U, "z9BC.2", "IBM System z9 BC GA2"),
  64    CPUDEF_INIT(0x2097, 10, 1, 43, 0x00000000U, "z10EC", "IBM System z10 EC GA1"),
  65    CPUDEF_INIT(0x2097, 10, 2, 43, 0x00000000U, "z10EC.2", "IBM System z10 EC GA2"),
  66    CPUDEF_INIT(0x2098, 10, 2, 43, 0x00000000U, "z10BC", "IBM System z10 BC GA1"),
  67    CPUDEF_INIT(0x2097, 10, 3, 43, 0x00000000U, "z10EC.3", "IBM System z10 EC GA3"),
  68    CPUDEF_INIT(0x2098, 10, 3, 43, 0x00000000U, "z10BC.2", "IBM System z10 BC GA2"),
  69    CPUDEF_INIT(0x2817, 11, 1, 44, 0x08000000U, "z196", "IBM zEnterprise 196 GA1"),
  70    CPUDEF_INIT(0x2817, 11, 2, 44, 0x08000000U, "z196.2", "IBM zEnterprise 196 GA2"),
  71    CPUDEF_INIT(0x2818, 11, 2, 44, 0x08000000U, "z114", "IBM zEnterprise 114 GA1"),
  72    CPUDEF_INIT(0x2827, 12, 1, 44, 0x08000000U, "zEC12", "IBM zEnterprise EC12 GA1"),
  73    CPUDEF_INIT(0x2827, 12, 2, 44, 0x08000000U, "zEC12.2", "IBM zEnterprise EC12 GA2"),
  74    CPUDEF_INIT(0x2828, 12, 2, 44, 0x08000000U, "zBC12", "IBM zEnterprise BC12 GA1"),
  75    CPUDEF_INIT(0x2964, 13, 1, 47, 0x08000000U, "z13", "IBM z13 GA1"),
  76    CPUDEF_INIT(0x2964, 13, 2, 47, 0x08000000U, "z13.2", "IBM z13 GA2"),
  77    CPUDEF_INIT(0x2965, 13, 2, 47, 0x08000000U, "z13s", "IBM z13s GA1"),
  78    CPUDEF_INIT(0x3906, 14, 1, 47, 0x08000000U, "z14", "IBM z14 GA1"),
  79};
  80
  81/* features part of a base model but not relevant for finding a base model */
  82S390FeatBitmap ignored_base_feat;
  83
  84void s390_cpudef_featoff(uint8_t gen, uint8_t ec_ga, S390Feat feat)
  85{
  86    const S390CPUDef *def;
  87
  88    def = s390_find_cpu_def(0, gen, ec_ga, NULL);
  89    clear_bit(feat, (unsigned long *)&def->default_feat);
  90}
  91
  92void s390_cpudef_featoff_greater(uint8_t gen, uint8_t ec_ga, S390Feat feat)
  93{
  94    int i;
  95
  96    for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) {
  97        const S390CPUDef *def = &s390_cpu_defs[i];
  98
  99        if (def->gen < gen) {
 100            continue;
 101        }
 102        if (def->gen == gen && def->ec_ga < ec_ga) {
 103            continue;
 104        }
 105
 106        clear_bit(feat, (unsigned long *)&def->default_feat);
 107    }
 108}
 109
 110uint32_t s390_get_hmfai(void)
 111{
 112    static S390CPU *cpu;
 113
 114    if (!cpu) {
 115        cpu = S390_CPU(qemu_get_cpu(0));
 116    }
 117
 118    if (!cpu || !cpu->model) {
 119        return 0;
 120    }
 121    return cpu->model->def->hmfai;
 122}
 123
 124uint8_t s390_get_mha_pow(void)
 125{
 126    static S390CPU *cpu;
 127
 128    if (!cpu) {
 129        cpu = S390_CPU(qemu_get_cpu(0));
 130    }
 131
 132    if (!cpu || !cpu->model) {
 133        return 0;
 134    }
 135    return cpu->model->def->mha_pow;
 136}
 137
 138uint32_t s390_get_ibc_val(void)
 139{
 140    uint16_t unblocked_ibc, lowest_ibc;
 141    static S390CPU *cpu;
 142
 143    if (!cpu) {
 144        cpu = S390_CPU(qemu_get_cpu(0));
 145    }
 146
 147    if (!cpu || !cpu->model) {
 148        return 0;
 149    }
 150    unblocked_ibc = s390_ibc_from_cpu_model(cpu->model);
 151    lowest_ibc = cpu->model->lowest_ibc;
 152    /* the lowest_ibc always has to be <= unblocked_ibc */
 153    if (!lowest_ibc || lowest_ibc > unblocked_ibc) {
 154        return 0;
 155    }
 156    return ((uint32_t) lowest_ibc << 16) | unblocked_ibc;
 157}
 158
 159void s390_get_feat_block(S390FeatType type, uint8_t *data)
 160{
 161    static S390CPU *cpu;
 162
 163    if (!cpu) {
 164        cpu = S390_CPU(qemu_get_cpu(0));
 165    }
 166
 167    if (!cpu || !cpu->model) {
 168        return;
 169    }
 170    s390_fill_feat_block(cpu->model->features, type, data);
 171}
 172
 173bool s390_has_feat(S390Feat feat)
 174{
 175    static S390CPU *cpu;
 176
 177    if (!cpu) {
 178        cpu = S390_CPU(qemu_get_cpu(0));
 179    }
 180
 181    if (!cpu || !cpu->model) {
 182#ifdef CONFIG_KVM
 183        if (kvm_enabled()) {
 184            if (feat == S390_FEAT_VECTOR) {
 185                return kvm_check_extension(kvm_state,
 186                                           KVM_CAP_S390_VECTOR_REGISTERS);
 187            }
 188            if (feat == S390_FEAT_RUNTIME_INSTRUMENTATION) {
 189                return kvm_s390_get_ri();
 190            }
 191            if (feat == S390_FEAT_MSA_EXT_3) {
 192                return true;
 193            }
 194        }
 195#endif
 196        return 0;
 197    }
 198    return test_bit(feat, cpu->model->features);
 199}
 200
 201uint8_t s390_get_gen_for_cpu_type(uint16_t type)
 202{
 203    int i;
 204
 205    for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) {
 206        if (s390_cpu_defs[i].type == type) {
 207            return s390_cpu_defs[i].gen;
 208        }
 209    }
 210    return 0;
 211}
 212
 213const S390CPUDef *s390_find_cpu_def(uint16_t type, uint8_t gen, uint8_t ec_ga,
 214                                    S390FeatBitmap features)
 215{
 216    const S390CPUDef *last_compatible = NULL;
 217    const S390CPUDef *matching_cpu_type = NULL;
 218    int i;
 219
 220    if (!gen) {
 221        ec_ga = 0;
 222    }
 223    if (!gen && type) {
 224        gen = s390_get_gen_for_cpu_type(type);
 225    }
 226
 227    for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) {
 228        const S390CPUDef *def = &s390_cpu_defs[i];
 229        S390FeatBitmap missing;
 230
 231        /* don't even try newer generations if we know the generation */
 232        if (gen) {
 233            if (def->gen > gen) {
 234                break;
 235            } else if (def->gen == gen && ec_ga && def->ec_ga > ec_ga) {
 236                break;
 237            }
 238        }
 239
 240        if (features) {
 241            /* see if the model satisfies the minimum features */
 242            bitmap_andnot(missing, def->base_feat, features, S390_FEAT_MAX);
 243            /*
 244             * Ignore certain features that are in the base model, but not
 245             * relevant for the search (esp. MSA subfunctions).
 246             */
 247            bitmap_andnot(missing, missing, ignored_base_feat, S390_FEAT_MAX);
 248            if (!bitmap_empty(missing, S390_FEAT_MAX)) {
 249                break;
 250            }
 251        }
 252
 253        /* stop the search if we found the exact model */
 254        if (def->type == type && def->ec_ga == ec_ga) {
 255            return def;
 256        }
 257        /* remember if we've at least seen one with the same cpu type */
 258        if (def->type == type) {
 259            matching_cpu_type = def;
 260        }
 261        last_compatible = def;
 262    }
 263    /* prefer the model with the same cpu type, esp. don't take the BC for EC */
 264    if (matching_cpu_type) {
 265        return matching_cpu_type;
 266    }
 267    return last_compatible;
 268}
 269
 270struct S390PrintCpuListInfo {
 271    FILE *f;
 272    fprintf_function print;
 273};
 274
 275static void print_cpu_model_list(ObjectClass *klass, void *opaque)
 276{
 277    struct S390PrintCpuListInfo *info = opaque;
 278    S390CPUClass *scc = S390_CPU_CLASS(klass);
 279    char *name = g_strdup(object_class_get_name(klass));
 280    const char *details = "";
 281
 282    if (scc->is_static) {
 283        details = "(static, migration-safe)";
 284    } else if (scc->is_migration_safe) {
 285        details = "(migration-safe)";
 286    }
 287
 288    /* strip off the -s390-cpu */
 289    g_strrstr(name, "-" TYPE_S390_CPU)[0] = 0;
 290    (*info->print)(info->f, "s390 %-15s %-35s %s\n", name, scc->desc,
 291                   details);
 292    g_free(name);
 293}
 294
 295void s390_cpu_list(FILE *f, fprintf_function print)
 296{
 297    struct S390PrintCpuListInfo info = {
 298        .f = f,
 299        .print = print,
 300    };
 301    S390FeatGroup group;
 302    S390Feat feat;
 303
 304    object_class_foreach(print_cpu_model_list, TYPE_S390_CPU, false, &info);
 305
 306    (*print)(f, "\nRecognized feature flags:\n");
 307    for (feat = 0; feat < S390_FEAT_MAX; feat++) {
 308        const S390FeatDef *def = s390_feat_def(feat);
 309
 310        (*print)(f, "%-20s %-50s\n", def->name, def->desc);
 311    }
 312
 313    (*print)(f, "\nRecognized feature groups:\n");
 314    for (group = 0; group < S390_FEAT_GROUP_MAX; group++) {
 315        const S390FeatGroupDef *def = s390_feat_group_def(group);
 316
 317        (*print)(f, "%-20s %-50s\n", def->name, def->desc);
 318    }
 319}
 320
 321static S390CPUModel *get_max_cpu_model(Error **errp);
 322
 323#ifndef CONFIG_USER_ONLY
 324static void list_add_feat(const char *name, void *opaque);
 325
 326static void check_unavailable_features(const S390CPUModel *max_model,
 327                                       const S390CPUModel *model,
 328                                       strList **unavailable)
 329{
 330    S390FeatBitmap missing;
 331
 332    /* check general model compatibility */
 333    if (max_model->def->gen < model->def->gen ||
 334        (max_model->def->gen == model->def->gen &&
 335         max_model->def->ec_ga < model->def->ec_ga)) {
 336        list_add_feat("type", unavailable);
 337    }
 338
 339    /* detect missing features if any to properly report them */
 340    bitmap_andnot(missing, model->features, max_model->features,
 341                  S390_FEAT_MAX);
 342    if (!bitmap_empty(missing, S390_FEAT_MAX)) {
 343        s390_feat_bitmap_to_ascii(missing, unavailable, list_add_feat);
 344    }
 345}
 346
 347struct CpuDefinitionInfoListData {
 348    CpuDefinitionInfoList *list;
 349    S390CPUModel *model;
 350};
 351
 352static void create_cpu_model_list(ObjectClass *klass, void *opaque)
 353{
 354    struct CpuDefinitionInfoListData *cpu_list_data = opaque;
 355    CpuDefinitionInfoList **cpu_list = &cpu_list_data->list;
 356    CpuDefinitionInfoList *entry;
 357    CpuDefinitionInfo *info;
 358    char *name = g_strdup(object_class_get_name(klass));
 359    S390CPUClass *scc = S390_CPU_CLASS(klass);
 360
 361    /* strip off the -s390-cpu */
 362    g_strrstr(name, "-" TYPE_S390_CPU)[0] = 0;
 363    info = g_malloc0(sizeof(*info));
 364    info->name = name;
 365    info->has_migration_safe = true;
 366    info->migration_safe = scc->is_migration_safe;
 367    info->q_static = scc->is_static;
 368    info->q_typename = g_strdup(object_class_get_name(klass));
 369    /* check for unavailable features */
 370    if (cpu_list_data->model) {
 371        Object *obj;
 372        S390CPU *sc;
 373        obj = object_new(object_class_get_name(klass));
 374        sc = S390_CPU(obj);
 375        if (sc->model) {
 376            info->has_unavailable_features = true;
 377            check_unavailable_features(cpu_list_data->model, sc->model,
 378                                       &info->unavailable_features);
 379        }
 380        object_unref(obj);
 381    }
 382
 383    entry = g_malloc0(sizeof(*entry));
 384    entry->value = info;
 385    entry->next = *cpu_list;
 386    *cpu_list = entry;
 387}
 388
 389CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
 390{
 391    struct CpuDefinitionInfoListData list_data = {
 392        .list = NULL,
 393    };
 394
 395    list_data.model = get_max_cpu_model(errp);
 396    if (*errp) {
 397        error_free(*errp);
 398        *errp = NULL;
 399    }
 400
 401    object_class_foreach(create_cpu_model_list, TYPE_S390_CPU, false,
 402                         &list_data);
 403
 404    return list_data.list;
 405}
 406
 407static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info,
 408                                Error **errp)
 409{
 410    const QDict *qdict = NULL;
 411    const QDictEntry *e;
 412    Visitor *visitor;
 413    ObjectClass *oc;
 414    S390CPU *cpu;
 415    Object *obj;
 416
 417    if (info->props) {
 418        qdict = qobject_to_qdict(info->props);
 419        if (!qdict) {
 420            error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
 421            return;
 422        }
 423    }
 424
 425    oc = cpu_class_by_name(TYPE_S390_CPU, info->name);
 426    if (!oc) {
 427        error_setg(errp, "The CPU definition \'%s\' is unknown.", info->name);
 428        return;
 429    }
 430    if (S390_CPU_CLASS(oc)->kvm_required && !kvm_enabled()) {
 431        error_setg(errp, "The CPU definition '%s' requires KVM", info->name);
 432        return;
 433    }
 434    obj = object_new(object_class_get_name(oc));
 435    cpu = S390_CPU(obj);
 436
 437    if (!cpu->model) {
 438        error_setg(errp, "Details about the host CPU model are not available, "
 439                         "it cannot be used.");
 440        object_unref(obj);
 441        return;
 442    }
 443
 444    if (qdict) {
 445        visitor = qobject_input_visitor_new(info->props);
 446        visit_start_struct(visitor, NULL, NULL, 0, errp);
 447        if (*errp) {
 448            object_unref(obj);
 449            return;
 450        }
 451        for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
 452            object_property_set(obj, visitor, e->key, errp);
 453            if (*errp) {
 454                break;
 455            }
 456        }
 457        if (!*errp) {
 458            visit_check_struct(visitor, errp);
 459        }
 460        visit_end_struct(visitor, NULL);
 461        visit_free(visitor);
 462        if (*errp) {
 463            object_unref(obj);
 464            return;
 465        }
 466    }
 467
 468    /* copy the model and throw the cpu away */
 469    memcpy(model, cpu->model, sizeof(*model));
 470    object_unref(obj);
 471}
 472
 473static void qdict_add_disabled_feat(const char *name, void *opaque)
 474{
 475    qdict_put_bool(opaque, name, false);
 476}
 477
 478static void qdict_add_enabled_feat(const char *name, void *opaque)
 479{
 480    qdict_put_bool(opaque, name, true);
 481}
 482
 483/* convert S390CPUDef into a static CpuModelInfo */
 484static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model,
 485                                bool delta_changes)
 486{
 487    QDict *qdict = qdict_new();
 488    S390FeatBitmap bitmap;
 489
 490    /* always fallback to the static base model */
 491    info->name = g_strdup_printf("%s-base", model->def->name);
 492
 493    if (delta_changes) {
 494        /* features deleted from the base feature set */
 495        bitmap_andnot(bitmap, model->def->base_feat, model->features,
 496                      S390_FEAT_MAX);
 497        if (!bitmap_empty(bitmap, S390_FEAT_MAX)) {
 498            s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_disabled_feat);
 499        }
 500
 501        /* features added to the base feature set */
 502        bitmap_andnot(bitmap, model->features, model->def->base_feat,
 503                      S390_FEAT_MAX);
 504        if (!bitmap_empty(bitmap, S390_FEAT_MAX)) {
 505            s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_enabled_feat);
 506        }
 507    } else {
 508        /* expand all features */
 509        s390_feat_bitmap_to_ascii(model->features, qdict,
 510                                  qdict_add_enabled_feat);
 511        bitmap_complement(bitmap, model->features, S390_FEAT_MAX);
 512        s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_disabled_feat);
 513    }
 514
 515    if (!qdict_size(qdict)) {
 516        QDECREF(qdict);
 517    } else {
 518        info->props = QOBJECT(qdict);
 519        info->has_props = true;
 520    }
 521}
 522
 523CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type,
 524                                                      CpuModelInfo *model,
 525                                                      Error **errp)
 526{
 527    CpuModelExpansionInfo *expansion_info = NULL;
 528    S390CPUModel s390_model;
 529    bool delta_changes = false;
 530
 531    /* convert it to our internal representation */
 532    cpu_model_from_info(&s390_model, model, errp);
 533    if (*errp) {
 534        return NULL;
 535    }
 536
 537    if (type == CPU_MODEL_EXPANSION_TYPE_STATIC) {
 538        delta_changes = true;
 539    } else if (type != CPU_MODEL_EXPANSION_TYPE_FULL) {
 540        error_setg(errp, "The requested expansion type is not supported.");
 541        return NULL;
 542    }
 543
 544    /* convert it back to a static representation */
 545    expansion_info = g_malloc0(sizeof(*expansion_info));
 546    expansion_info->model = g_malloc0(sizeof(*expansion_info->model));
 547    cpu_info_from_model(expansion_info->model, &s390_model, delta_changes);
 548    return expansion_info;
 549}
 550
 551static void list_add_feat(const char *name, void *opaque)
 552{
 553    strList **last = (strList **) opaque;
 554    strList *entry;
 555
 556    entry = g_malloc0(sizeof(*entry));
 557    entry->value = g_strdup(name);
 558    entry->next = *last;
 559    *last = entry;
 560}
 561
 562CpuModelCompareInfo *arch_query_cpu_model_comparison(CpuModelInfo *infoa,
 563                                                     CpuModelInfo *infob,
 564                                                     Error **errp)
 565{
 566    CpuModelCompareResult feat_result, gen_result;
 567    CpuModelCompareInfo *compare_info;
 568    S390FeatBitmap missing, added;
 569    S390CPUModel modela, modelb;
 570
 571    /* convert both models to our internal representation */
 572    cpu_model_from_info(&modela, infoa, errp);
 573    if (*errp) {
 574        return NULL;
 575    }
 576    cpu_model_from_info(&modelb, infob, errp);
 577    if (*errp) {
 578        return NULL;
 579    }
 580    compare_info = g_malloc0(sizeof(*compare_info));
 581
 582    /* check the cpu generation and ga level */
 583    if (modela.def->gen == modelb.def->gen) {
 584        if (modela.def->ec_ga == modelb.def->ec_ga) {
 585            /* ec and corresponding bc are identical */
 586            gen_result = CPU_MODEL_COMPARE_RESULT_IDENTICAL;
 587        } else if (modela.def->ec_ga < modelb.def->ec_ga) {
 588            gen_result = CPU_MODEL_COMPARE_RESULT_SUBSET;
 589        } else {
 590            gen_result = CPU_MODEL_COMPARE_RESULT_SUPERSET;
 591        }
 592    } else if (modela.def->gen < modelb.def->gen) {
 593        gen_result = CPU_MODEL_COMPARE_RESULT_SUBSET;
 594    } else {
 595        gen_result = CPU_MODEL_COMPARE_RESULT_SUPERSET;
 596    }
 597    if (gen_result != CPU_MODEL_COMPARE_RESULT_IDENTICAL) {
 598        /* both models cannot be made identical */
 599        list_add_feat("type", &compare_info->responsible_properties);
 600    }
 601
 602    /* check the feature set */
 603    if (bitmap_equal(modela.features, modelb.features, S390_FEAT_MAX)) {
 604        feat_result = CPU_MODEL_COMPARE_RESULT_IDENTICAL;
 605    } else {
 606        bitmap_andnot(missing, modela.features, modelb.features, S390_FEAT_MAX);
 607        s390_feat_bitmap_to_ascii(missing,
 608                                  &compare_info->responsible_properties,
 609                                  list_add_feat);
 610        bitmap_andnot(added, modelb.features, modela.features, S390_FEAT_MAX);
 611        s390_feat_bitmap_to_ascii(added, &compare_info->responsible_properties,
 612                                  list_add_feat);
 613        if (bitmap_empty(missing, S390_FEAT_MAX)) {
 614            feat_result = CPU_MODEL_COMPARE_RESULT_SUBSET;
 615        } else if (bitmap_empty(added, S390_FEAT_MAX)) {
 616            feat_result = CPU_MODEL_COMPARE_RESULT_SUPERSET;
 617        } else {
 618            feat_result = CPU_MODEL_COMPARE_RESULT_INCOMPATIBLE;
 619        }
 620    }
 621
 622    /* combine the results */
 623    if (gen_result == feat_result) {
 624        compare_info->result = gen_result;
 625    } else if (feat_result == CPU_MODEL_COMPARE_RESULT_IDENTICAL) {
 626        compare_info->result = gen_result;
 627    } else if (gen_result == CPU_MODEL_COMPARE_RESULT_IDENTICAL) {
 628        compare_info->result = feat_result;
 629    } else {
 630        compare_info->result = CPU_MODEL_COMPARE_RESULT_INCOMPATIBLE;
 631    }
 632    return compare_info;
 633}
 634
 635CpuModelBaselineInfo *arch_query_cpu_model_baseline(CpuModelInfo *infoa,
 636                                                    CpuModelInfo *infob,
 637                                                    Error **errp)
 638{
 639    CpuModelBaselineInfo *baseline_info;
 640    S390CPUModel modela, modelb, model;
 641    uint16_t cpu_type;
 642    uint8_t max_gen_ga;
 643    uint8_t max_gen;
 644
 645    /* convert both models to our internal representation */
 646    cpu_model_from_info(&modela, infoa, errp);
 647    if (*errp) {
 648        return NULL;
 649    }
 650
 651    cpu_model_from_info(&modelb, infob, errp);
 652    if (*errp) {
 653        return NULL;
 654    }
 655
 656    /* features both models support */
 657    bitmap_and(model.features, modela.features, modelb.features, S390_FEAT_MAX);
 658
 659    /* detect the maximum model not regarding features */
 660    if (modela.def->gen == modelb.def->gen) {
 661        if (modela.def->type == modelb.def->type) {
 662            cpu_type = modela.def->type;
 663        } else {
 664            cpu_type = 0;
 665        }
 666        max_gen = modela.def->gen;
 667        max_gen_ga = MIN(modela.def->ec_ga, modelb.def->ec_ga);
 668    } else if (modela.def->gen > modelb.def->gen) {
 669        cpu_type = modelb.def->type;
 670        max_gen = modelb.def->gen;
 671        max_gen_ga = modelb.def->ec_ga;
 672    } else {
 673        cpu_type = modela.def->type;
 674        max_gen = modela.def->gen;
 675        max_gen_ga = modela.def->ec_ga;
 676    }
 677
 678    model.def = s390_find_cpu_def(cpu_type, max_gen, max_gen_ga,
 679                                  model.features);
 680    /* strip off features not part of the max model */
 681    bitmap_and(model.features, model.features, model.def->full_feat,
 682               S390_FEAT_MAX);
 683
 684    baseline_info = g_malloc0(sizeof(*baseline_info));
 685    baseline_info->model = g_malloc0(sizeof(*baseline_info->model));
 686    cpu_info_from_model(baseline_info->model, &model, true);
 687    return baseline_info;
 688}
 689#endif
 690
 691static void check_consistency(const S390CPUModel *model)
 692{
 693    static int dep[][2] = {
 694        { S390_FEAT_IPTE_RANGE, S390_FEAT_DAT_ENH },
 695        { S390_FEAT_IDTE_SEGMENT, S390_FEAT_DAT_ENH },
 696        { S390_FEAT_IDTE_REGION, S390_FEAT_DAT_ENH },
 697        { S390_FEAT_IDTE_REGION, S390_FEAT_IDTE_SEGMENT },
 698        { S390_FEAT_LOCAL_TLB_CLEARING, S390_FEAT_DAT_ENH},
 699        { S390_FEAT_LONG_DISPLACEMENT_FAST, S390_FEAT_LONG_DISPLACEMENT },
 700        { S390_FEAT_DFP_FAST, S390_FEAT_DFP },
 701        { S390_FEAT_TRANSACTIONAL_EXE, S390_FEAT_STFLE_49 },
 702        { S390_FEAT_EDAT_2, S390_FEAT_EDAT},
 703        { S390_FEAT_MSA_EXT_5, S390_FEAT_KIMD_SHA_512 },
 704        { S390_FEAT_MSA_EXT_5, S390_FEAT_KLMD_SHA_512 },
 705        { S390_FEAT_MSA_EXT_4, S390_FEAT_MSA_EXT_3 },
 706        { S390_FEAT_SIE_CMMA, S390_FEAT_CMM },
 707        { S390_FEAT_SIE_CMMA, S390_FEAT_SIE_GSLS },
 708        { S390_FEAT_SIE_PFMFI, S390_FEAT_EDAT },
 709        { S390_FEAT_MSA_EXT_8, S390_FEAT_MSA_EXT_3 },
 710        { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_TOD_CLOCK_STEERING },
 711        { S390_FEAT_VECTOR_PACKED_DECIMAL, S390_FEAT_VECTOR },
 712        { S390_FEAT_VECTOR_ENH, S390_FEAT_VECTOR },
 713        { S390_FEAT_INSTRUCTION_EXEC_PROT, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2 },
 714        { S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, S390_FEAT_ESOP },
 715        { S390_FEAT_CMM_NT, S390_FEAT_CMM },
 716        { S390_FEAT_GUARDED_STORAGE, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2 },
 717        { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_STORE_CLOCK_FAST },
 718        { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_TOD_CLOCK_STEERING },
 719        { S390_FEAT_SEMAPHORE_ASSIST, S390_FEAT_STFLE_49 },
 720        { S390_FEAT_KIMD_SHA3_224, S390_FEAT_MSA },
 721        { S390_FEAT_KIMD_SHA3_256, S390_FEAT_MSA },
 722        { S390_FEAT_KIMD_SHA3_384, S390_FEAT_MSA },
 723        { S390_FEAT_KIMD_SHA3_512, S390_FEAT_MSA },
 724        { S390_FEAT_KIMD_SHAKE_128, S390_FEAT_MSA },
 725        { S390_FEAT_KIMD_SHAKE_256, S390_FEAT_MSA },
 726        { S390_FEAT_KLMD_SHA3_224, S390_FEAT_MSA },
 727        { S390_FEAT_KLMD_SHA3_256, S390_FEAT_MSA },
 728        { S390_FEAT_KLMD_SHA3_384, S390_FEAT_MSA },
 729        { S390_FEAT_KLMD_SHA3_512, S390_FEAT_MSA },
 730        { S390_FEAT_KLMD_SHAKE_128, S390_FEAT_MSA },
 731        { S390_FEAT_KLMD_SHAKE_256, S390_FEAT_MSA },
 732        { S390_FEAT_PRNO_TRNG_QRTCR, S390_FEAT_MSA_EXT_5 },
 733        { S390_FEAT_PRNO_TRNG, S390_FEAT_MSA_EXT_5 },
 734        { S390_FEAT_SIE_KSS, S390_FEAT_SIE_F2 },
 735    };
 736    int i;
 737
 738    for (i = 0; i < ARRAY_SIZE(dep); i++) {
 739        if (test_bit(dep[i][0], model->features) &&
 740            !test_bit(dep[i][1], model->features)) {
 741            warn_report("\'%s\' requires \'%s\'.",
 742                        s390_feat_def(dep[i][0])->name,
 743                        s390_feat_def(dep[i][1])->name);
 744        }
 745    }
 746}
 747
 748static void error_prepend_missing_feat(const char *name, void *opaque)
 749{
 750    error_prepend((Error **) opaque, "%s ", name);
 751}
 752
 753static void check_compatibility(const S390CPUModel *max_model,
 754                                const S390CPUModel *model, Error **errp)
 755{
 756    S390FeatBitmap missing;
 757
 758    if (model->def->gen > max_model->def->gen) {
 759        error_setg(errp, "Selected CPU generation is too new. Maximum "
 760                   "supported model in the configuration: \'%s\'",
 761                   max_model->def->name);
 762        return;
 763    } else if (model->def->gen == max_model->def->gen &&
 764               model->def->ec_ga > max_model->def->ec_ga) {
 765        error_setg(errp, "Selected CPU GA level is too new. Maximum "
 766                   "supported model in the configuration: \'%s\'",
 767                   max_model->def->name);
 768        return;
 769    }
 770
 771    /* detect the missing features to properly report them */
 772    bitmap_andnot(missing, model->features, max_model->features, S390_FEAT_MAX);
 773    if (bitmap_empty(missing, S390_FEAT_MAX)) {
 774        return;
 775    }
 776
 777    error_setg(errp, " ");
 778    s390_feat_bitmap_to_ascii(missing, errp, error_prepend_missing_feat);
 779    error_prepend(errp, "Some features requested in the CPU model are not "
 780                  "available in the configuration: ");
 781}
 782
 783/**
 784 * The base TCG CPU model "qemu" is based on the z900. However, we already
 785 * can also emulate some additional features of later CPU generations, so
 786 * we add these additional feature bits here.
 787 */
 788static void add_qemu_cpu_model_features(S390FeatBitmap fbm)
 789{
 790    static const int feats[] = {
 791        S390_FEAT_DAT_ENH,
 792        S390_FEAT_IDTE_SEGMENT,
 793        S390_FEAT_STFLE,
 794        S390_FEAT_EXTENDED_IMMEDIATE,
 795        S390_FEAT_EXTENDED_TRANSLATION_2,
 796        S390_FEAT_EXTENDED_TRANSLATION_3,
 797        S390_FEAT_LONG_DISPLACEMENT,
 798        S390_FEAT_LONG_DISPLACEMENT_FAST,
 799        S390_FEAT_ETF2_ENH,
 800        S390_FEAT_STORE_CLOCK_FAST,
 801        S390_FEAT_MOVE_WITH_OPTIONAL_SPEC,
 802        S390_FEAT_ETF3_ENH,
 803        S390_FEAT_COMPARE_AND_SWAP_AND_STORE,
 804        S390_FEAT_COMPARE_AND_SWAP_AND_STORE_2,
 805        S390_FEAT_GENERAL_INSTRUCTIONS_EXT,
 806        S390_FEAT_EXECUTE_EXT,
 807        S390_FEAT_FLOATING_POINT_SUPPPORT_ENH,
 808        S390_FEAT_STFLE_45,
 809        S390_FEAT_STFLE_49,
 810        S390_FEAT_LOCAL_TLB_CLEARING,
 811        S390_FEAT_STFLE_53,
 812    };
 813    int i;
 814
 815    for (i = 0; i < ARRAY_SIZE(feats); i++) {
 816        set_bit(feats[i], fbm);
 817    }
 818}
 819
 820static S390CPUModel *get_max_cpu_model(Error **errp)
 821{
 822    static S390CPUModel max_model;
 823    static bool cached;
 824
 825    if (cached) {
 826        return &max_model;
 827    }
 828
 829    if (kvm_enabled()) {
 830        kvm_s390_get_host_cpu_model(&max_model, errp);
 831    } else {
 832        /* TCG emulates a z900 (with some optional additional features) */
 833        max_model.def = &s390_cpu_defs[0];
 834        bitmap_copy(max_model.features, max_model.def->default_feat,
 835                    S390_FEAT_MAX);
 836        add_qemu_cpu_model_features(max_model.features);
 837    }
 838    if (!*errp) {
 839        cached = true;
 840        return &max_model;
 841    }
 842    return NULL;
 843}
 844
 845static inline void apply_cpu_model(const S390CPUModel *model, Error **errp)
 846{
 847#ifndef CONFIG_USER_ONLY
 848    static S390CPUModel applied_model;
 849    static bool applied;
 850
 851    /*
 852     * We have the same model for all VCPUs. KVM can only be configured before
 853     * any VCPUs are defined in KVM.
 854     */
 855    if (applied) {
 856        if (model && memcmp(&applied_model, model, sizeof(S390CPUModel))) {
 857            error_setg(errp, "Mixed CPU models are not supported on s390x.");
 858        }
 859        return;
 860    }
 861
 862    if (kvm_enabled()) {
 863        kvm_s390_apply_cpu_model(model, errp);
 864    }
 865
 866    if (!*errp) {
 867        applied = true;
 868        if (model) {
 869            applied_model = *model;
 870        }
 871    }
 872#endif
 873}
 874
 875void s390_realize_cpu_model(CPUState *cs, Error **errp)
 876{
 877    S390CPUClass *xcc = S390_CPU_GET_CLASS(cs);
 878    S390CPU *cpu = S390_CPU(cs);
 879    const S390CPUModel *max_model;
 880
 881    if (xcc->kvm_required && !kvm_enabled()) {
 882        error_setg(errp, "CPU definition requires KVM");
 883        return;
 884    }
 885
 886    if (!cpu->model) {
 887        /* no host model support -> perform compatibility stuff */
 888        apply_cpu_model(NULL, errp);
 889        return;
 890    }
 891
 892    max_model = get_max_cpu_model(errp);
 893    if (*errp) {
 894        error_prepend(errp, "CPU models are not available: ");
 895        return;
 896    }
 897
 898    /* copy over properties that can vary */
 899    cpu->model->lowest_ibc = max_model->lowest_ibc;
 900    cpu->model->cpu_id = max_model->cpu_id;
 901    cpu->model->cpu_id_format = max_model->cpu_id_format;
 902    cpu->model->cpu_ver = max_model->cpu_ver;
 903
 904    check_consistency(cpu->model);
 905    check_compatibility(max_model, cpu->model, errp);
 906    if (*errp) {
 907        return;
 908    }
 909
 910    apply_cpu_model(cpu->model, errp);
 911
 912    cpu->env.cpuid = s390_cpuid_from_cpu_model(cpu->model);
 913    if (tcg_enabled()) {
 914        /* basic mode, write the cpu address into the first 4 bit of the ID */
 915        cpu->env.cpuid = deposit64(cpu->env.cpuid, 54, 4, cpu->env.cpu_num);
 916    }
 917}
 918
 919static void get_feature(Object *obj, Visitor *v, const char *name,
 920                        void *opaque, Error **errp)
 921{
 922    S390Feat feat = (S390Feat) opaque;
 923    S390CPU *cpu = S390_CPU(obj);
 924    bool value;
 925
 926    if (!cpu->model) {
 927        error_setg(errp, "Details about the host CPU model are not available, "
 928                         "features cannot be queried.");
 929        return;
 930    }
 931
 932    value = test_bit(feat, cpu->model->features);
 933    visit_type_bool(v, name, &value, errp);
 934}
 935
 936static void set_feature(Object *obj, Visitor *v, const char *name,
 937                        void *opaque, Error **errp)
 938{
 939    S390Feat feat = (S390Feat) opaque;
 940    DeviceState *dev = DEVICE(obj);
 941    S390CPU *cpu = S390_CPU(obj);
 942    bool value;
 943
 944    if (dev->realized) {
 945        error_setg(errp, "Attempt to set property '%s' on '%s' after "
 946                   "it was realized", name, object_get_typename(obj));
 947        return;
 948    } else if (!cpu->model) {
 949        error_setg(errp, "Details about the host CPU model are not available, "
 950                         "features cannot be changed.");
 951        return;
 952    }
 953
 954    visit_type_bool(v, name, &value, errp);
 955    if (*errp) {
 956        return;
 957    }
 958    if (value) {
 959        if (!test_bit(feat, cpu->model->def->full_feat)) {
 960            error_setg(errp, "Feature '%s' is not available for CPU model '%s',"
 961                       " it was introduced with later models.",
 962                       name, cpu->model->def->name);
 963            return;
 964        }
 965        set_bit(feat, cpu->model->features);
 966    } else {
 967        clear_bit(feat, cpu->model->features);
 968    }
 969}
 970
 971static void get_feature_group(Object *obj, Visitor *v, const char *name,
 972                              void *opaque, Error **errp)
 973{
 974    S390FeatGroup group = (S390FeatGroup) opaque;
 975    const S390FeatGroupDef *def = s390_feat_group_def(group);
 976    S390CPU *cpu = S390_CPU(obj);
 977    S390FeatBitmap tmp;
 978    bool value;
 979
 980    if (!cpu->model) {
 981        error_setg(errp, "Details about the host CPU model are not available, "
 982                         "features cannot be queried.");
 983        return;
 984    }
 985
 986    /* a group is enabled if all features are enabled */
 987    bitmap_and(tmp, cpu->model->features, def->feat, S390_FEAT_MAX);
 988    value = bitmap_equal(tmp, def->feat, S390_FEAT_MAX);
 989    visit_type_bool(v, name, &value, errp);
 990}
 991
 992static void set_feature_group(Object *obj, Visitor *v, const char *name,
 993                              void *opaque, Error **errp)
 994{
 995    S390FeatGroup group = (S390FeatGroup) opaque;
 996    const S390FeatGroupDef *def = s390_feat_group_def(group);
 997    DeviceState *dev = DEVICE(obj);
 998    S390CPU *cpu = S390_CPU(obj);
 999    bool value;
1000
1001    if (dev->realized) {
1002        error_setg(errp, "Attempt to set property '%s' on '%s' after "
1003                   "it was realized", name, object_get_typename(obj));
1004        return;
1005    } else if (!cpu->model) {
1006        error_setg(errp, "Details about the host CPU model are not available, "
1007                         "features cannot be changed.");
1008        return;
1009    }
1010
1011    visit_type_bool(v, name, &value, errp);
1012    if (*errp) {
1013        return;
1014    }
1015    if (value) {
1016        /* groups are added in one shot, so an intersect is sufficient */
1017        if (!bitmap_intersects(def->feat, cpu->model->def->full_feat,
1018                               S390_FEAT_MAX)) {
1019            error_setg(errp, "Group '%s' is not available for CPU model '%s',"
1020                       " it was introduced with later models.",
1021                       name, cpu->model->def->name);
1022            return;
1023        }
1024        bitmap_or(cpu->model->features, cpu->model->features, def->feat,
1025                  S390_FEAT_MAX);
1026    } else {
1027        bitmap_andnot(cpu->model->features, cpu->model->features, def->feat,
1028                      S390_FEAT_MAX);
1029    }
1030}
1031
1032void s390_cpu_model_register_props(Object *obj)
1033{
1034    S390FeatGroup group;
1035    S390Feat feat;
1036
1037    for (feat = 0; feat < S390_FEAT_MAX; feat++) {
1038        const S390FeatDef *def = s390_feat_def(feat);
1039        object_property_add(obj, def->name, "bool", get_feature,
1040                            set_feature, NULL, (void *) feat, NULL);
1041        object_property_set_description(obj, def->name, def->desc , NULL);
1042    }
1043    for (group = 0; group < S390_FEAT_GROUP_MAX; group++) {
1044        const S390FeatGroupDef *def = s390_feat_group_def(group);
1045        object_property_add(obj, def->name, "bool", get_feature_group,
1046                            set_feature_group, NULL, (void *) group, NULL);
1047        object_property_set_description(obj, def->name, def->desc , NULL);
1048    }
1049}
1050
1051static void s390_cpu_model_initfn(Object *obj)
1052{
1053    S390CPU *cpu = S390_CPU(obj);
1054    S390CPUClass *xcc = S390_CPU_GET_CLASS(cpu);
1055
1056    cpu->model = g_malloc0(sizeof(*cpu->model));
1057    /* copy the model, so we can modify it */
1058    cpu->model->def = xcc->cpu_def;
1059    if (xcc->is_static) {
1060        /* base model - features will never change */
1061        bitmap_copy(cpu->model->features, cpu->model->def->base_feat,
1062                    S390_FEAT_MAX);
1063    } else {
1064        /* latest model - features can change */
1065        bitmap_copy(cpu->model->features,
1066                    cpu->model->def->default_feat, S390_FEAT_MAX);
1067    }
1068}
1069
1070#ifdef CONFIG_KVM
1071static void s390_host_cpu_model_initfn(Object *obj)
1072{
1073    S390CPU *cpu = S390_CPU(obj);
1074    Error *err = NULL;
1075
1076    if (!kvm_enabled() || !kvm_s390_cpu_models_supported()) {
1077        return;
1078    }
1079
1080    cpu->model = g_malloc0(sizeof(*cpu->model));
1081    kvm_s390_get_host_cpu_model(cpu->model, &err);
1082    if (err) {
1083        error_report_err(err);
1084        g_free(cpu->model);
1085        /* fallback to unsupported cpu models */
1086        cpu->model = NULL;
1087    }
1088}
1089#endif
1090
1091static void s390_qemu_cpu_model_initfn(Object *obj)
1092{
1093    static S390CPUDef s390_qemu_cpu_defs;
1094    S390CPU *cpu = S390_CPU(obj);
1095
1096    cpu->model = g_malloc0(sizeof(*cpu->model));
1097    /* TCG emulates a z900 (with some optional additional features) */
1098    memcpy(&s390_qemu_cpu_defs, &s390_cpu_defs[0], sizeof(s390_qemu_cpu_defs));
1099    add_qemu_cpu_model_features(s390_qemu_cpu_defs.full_feat);
1100    cpu->model->def = &s390_qemu_cpu_defs;
1101    bitmap_copy(cpu->model->features, cpu->model->def->default_feat,
1102                S390_FEAT_MAX);
1103}
1104
1105static void s390_cpu_model_finalize(Object *obj)
1106{
1107    S390CPU *cpu = S390_CPU(obj);
1108
1109    g_free(cpu->model);
1110    cpu->model = NULL;
1111}
1112
1113static bool get_is_migration_safe(Object *obj, Error **errp)
1114{
1115    return S390_CPU_GET_CLASS(obj)->is_migration_safe;
1116}
1117
1118static bool get_is_static(Object *obj, Error **errp)
1119{
1120    return S390_CPU_GET_CLASS(obj)->is_static;
1121}
1122
1123static char *get_description(Object *obj, Error **errp)
1124{
1125    return g_strdup(S390_CPU_GET_CLASS(obj)->desc);
1126}
1127
1128void s390_cpu_model_class_register_props(ObjectClass *oc)
1129{
1130    object_class_property_add_bool(oc, "migration-safe", get_is_migration_safe,
1131                                   NULL, NULL);
1132    object_class_property_add_bool(oc, "static", get_is_static,
1133                                   NULL, NULL);
1134    object_class_property_add_str(oc, "description", get_description, NULL,
1135                                  NULL);
1136}
1137
1138#ifdef CONFIG_KVM
1139static void s390_host_cpu_model_class_init(ObjectClass *oc, void *data)
1140{
1141    S390CPUClass *xcc = S390_CPU_CLASS(oc);
1142
1143    xcc->kvm_required = true;
1144    xcc->desc = "KVM only: All recognized features";
1145}
1146#endif
1147
1148static void s390_base_cpu_model_class_init(ObjectClass *oc, void *data)
1149{
1150    S390CPUClass *xcc = S390_CPU_CLASS(oc);
1151
1152    /* all base models are migration safe */
1153    xcc->cpu_def = (const S390CPUDef *) data;
1154    xcc->is_migration_safe = true;
1155    xcc->is_static = true;
1156    xcc->desc = xcc->cpu_def->desc;
1157}
1158
1159static void s390_cpu_model_class_init(ObjectClass *oc, void *data)
1160{
1161    S390CPUClass *xcc = S390_CPU_CLASS(oc);
1162
1163    /* model that can change between QEMU versions */
1164    xcc->cpu_def = (const S390CPUDef *) data;
1165    xcc->is_migration_safe = true;
1166    xcc->desc = xcc->cpu_def->desc;
1167}
1168
1169static void s390_qemu_cpu_model_class_init(ObjectClass *oc, void *data)
1170{
1171    S390CPUClass *xcc = S390_CPU_CLASS(oc);
1172
1173    xcc->is_migration_safe = true;
1174    xcc->desc = g_strdup_printf("QEMU Virtual CPU version %s",
1175                                qemu_hw_version());
1176}
1177
1178#define S390_CPU_TYPE_SUFFIX "-" TYPE_S390_CPU
1179#define S390_CPU_TYPE_NAME(name) (name S390_CPU_TYPE_SUFFIX)
1180
1181/* Generate type name for a cpu model. Caller has to free the string. */
1182static char *s390_cpu_type_name(const char *model_name)
1183{
1184    return g_strdup_printf(S390_CPU_TYPE_NAME("%s"), model_name);
1185}
1186
1187/* Generate type name for a base cpu model. Caller has to free the string. */
1188static char *s390_base_cpu_type_name(const char *model_name)
1189{
1190    return g_strdup_printf(S390_CPU_TYPE_NAME("%s-base"), model_name);
1191}
1192
1193ObjectClass *s390_cpu_class_by_name(const char *name)
1194{
1195    char *typename = s390_cpu_type_name(name);
1196    ObjectClass *oc;
1197
1198    oc = object_class_by_name(typename);
1199    g_free(typename);
1200    return oc;
1201}
1202
1203static const TypeInfo qemu_s390_cpu_type_info = {
1204    .name = S390_CPU_TYPE_NAME("qemu"),
1205    .parent = TYPE_S390_CPU,
1206    .instance_init = s390_qemu_cpu_model_initfn,
1207    .instance_finalize = s390_cpu_model_finalize,
1208    .class_init = s390_qemu_cpu_model_class_init,
1209};
1210
1211#ifdef CONFIG_KVM
1212static const TypeInfo host_s390_cpu_type_info = {
1213    .name = S390_CPU_TYPE_NAME("host"),
1214    .parent = TYPE_S390_CPU,
1215    .instance_init = s390_host_cpu_model_initfn,
1216    .instance_finalize = s390_cpu_model_finalize,
1217    .class_init = s390_host_cpu_model_class_init,
1218};
1219#endif
1220
1221static void init_ignored_base_feat(void)
1222{
1223    static const int feats[] = {
1224         /* MSA subfunctions that could not be available on certain machines */
1225         S390_FEAT_KMAC_DEA,
1226         S390_FEAT_KMAC_TDEA_128,
1227         S390_FEAT_KMAC_TDEA_192,
1228         S390_FEAT_KMC_DEA,
1229         S390_FEAT_KMC_TDEA_128,
1230         S390_FEAT_KMC_TDEA_192,
1231         S390_FEAT_KM_DEA,
1232         S390_FEAT_KM_TDEA_128,
1233         S390_FEAT_KM_TDEA_192,
1234         S390_FEAT_KIMD_SHA_1,
1235         S390_FEAT_KLMD_SHA_1,
1236    };
1237    int i;
1238
1239    for (i = 0; i < ARRAY_SIZE(feats); i++) {
1240        set_bit(feats[i], ignored_base_feat);
1241    }
1242}
1243
1244static void register_types(void)
1245{
1246    int i;
1247
1248    init_ignored_base_feat();
1249
1250    /* init all bitmaps from gnerated data initially */
1251    for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) {
1252        s390_init_feat_bitmap(s390_cpu_defs[i].base_init,
1253                              s390_cpu_defs[i].base_feat);
1254        s390_init_feat_bitmap(s390_cpu_defs[i].default_init,
1255                              s390_cpu_defs[i].default_feat);
1256        s390_init_feat_bitmap(s390_cpu_defs[i].full_init,
1257                              s390_cpu_defs[i].full_feat);
1258    }
1259
1260    for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) {
1261        char *base_name = s390_base_cpu_type_name(s390_cpu_defs[i].name);
1262        TypeInfo ti_base = {
1263            .name = base_name,
1264            .parent = TYPE_S390_CPU,
1265            .instance_init = s390_cpu_model_initfn,
1266            .instance_finalize = s390_cpu_model_finalize,
1267            .class_init = s390_base_cpu_model_class_init,
1268            .class_data = (void *) &s390_cpu_defs[i],
1269        };
1270        char *name = s390_cpu_type_name(s390_cpu_defs[i].name);
1271        TypeInfo ti = {
1272            .name = name,
1273            .parent = TYPE_S390_CPU,
1274            .instance_init = s390_cpu_model_initfn,
1275            .instance_finalize = s390_cpu_model_finalize,
1276            .class_init = s390_cpu_model_class_init,
1277            .class_data = (void *) &s390_cpu_defs[i],
1278        };
1279
1280        type_register_static(&ti_base);
1281        type_register_static(&ti);
1282        g_free(base_name);
1283        g_free(name);
1284    }
1285
1286    type_register_static(&qemu_s390_cpu_type_info);
1287#ifdef CONFIG_KVM
1288    type_register_static(&host_s390_cpu_type_info);
1289#endif
1290}
1291
1292type_init(register_types)
1293