qemu/hw/s390x/s390-virtio-ccw.c
<<
>>
Prefs
   1/*
   2 * virtio ccw machine
   3 *
   4 * Copyright 2012 IBM Corp.
   5 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
   6 * Author(s): Cornelia Huck <cornelia.huck@de.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 "qapi/error.h"
  15#include "cpu.h"
  16#include "hw/boards.h"
  17#include "exec/address-spaces.h"
  18#include "hw/s390x/s390-virtio-hcall.h"
  19#include "hw/s390x/sclp.h"
  20#include "hw/s390x/s390_flic.h"
  21#include "hw/s390x/ioinst.h"
  22#include "hw/s390x/css.h"
  23#include "virtio-ccw.h"
  24#include "qemu/config-file.h"
  25#include "qemu/error-report.h"
  26#include "qemu/option.h"
  27#include "s390-pci-bus.h"
  28#include "hw/s390x/storage-keys.h"
  29#include "hw/s390x/storage-attributes.h"
  30#include "hw/s390x/event-facility.h"
  31#include "ipl.h"
  32#include "hw/s390x/s390-virtio-ccw.h"
  33#include "hw/s390x/css-bridge.h"
  34#include "hw/s390x/ap-bridge.h"
  35#include "migration/register.h"
  36#include "cpu_models.h"
  37#include "hw/nmi.h"
  38#include "hw/s390x/tod.h"
  39
  40S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
  41{
  42    static MachineState *ms;
  43
  44    if (!ms) {
  45        ms = MACHINE(qdev_get_machine());
  46        g_assert(ms->possible_cpus);
  47    }
  48
  49    /* CPU address corresponds to the core_id and the index */
  50    if (cpu_addr >= ms->possible_cpus->len) {
  51        return NULL;
  52    }
  53    return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
  54}
  55
  56static S390CPU *s390x_new_cpu(const char *typename, uint32_t core_id,
  57                              Error **errp)
  58{
  59    S390CPU *cpu = S390_CPU(object_new(typename));
  60    Error *err = NULL;
  61
  62    object_property_set_int(OBJECT(cpu), core_id, "core-id", &err);
  63    if (err != NULL) {
  64        goto out;
  65    }
  66    object_property_set_bool(OBJECT(cpu), true, "realized", &err);
  67
  68out:
  69    object_unref(OBJECT(cpu));
  70    if (err) {
  71        error_propagate(errp, err);
  72        cpu = NULL;
  73    }
  74    return cpu;
  75}
  76
  77static void s390_init_cpus(MachineState *machine)
  78{
  79    MachineClass *mc = MACHINE_GET_CLASS(machine);
  80    int i;
  81
  82    /* initialize possible_cpus */
  83    mc->possible_cpu_arch_ids(machine);
  84
  85    for (i = 0; i < smp_cpus; i++) {
  86        s390x_new_cpu(machine->cpu_type, i, &error_fatal);
  87    }
  88}
  89
  90static const char *const reset_dev_types[] = {
  91    TYPE_VIRTUAL_CSS_BRIDGE,
  92    "s390-sclp-event-facility",
  93    "s390-flic",
  94    "diag288",
  95};
  96
  97static void subsystem_reset(void)
  98{
  99    DeviceState *dev;
 100    int i;
 101
 102    for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) {
 103        dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL));
 104        if (dev) {
 105            qdev_reset_all(dev);
 106        }
 107    }
 108}
 109
 110static int virtio_ccw_hcall_notify(const uint64_t *args)
 111{
 112    uint64_t subch_id = args[0];
 113    uint64_t queue = args[1];
 114    SubchDev *sch;
 115    int cssid, ssid, schid, m;
 116
 117    if (ioinst_disassemble_sch_ident(subch_id, &m, &cssid, &ssid, &schid)) {
 118        return -EINVAL;
 119    }
 120    sch = css_find_subch(m, cssid, ssid, schid);
 121    if (!sch || !css_subch_visible(sch)) {
 122        return -EINVAL;
 123    }
 124    if (queue >= VIRTIO_QUEUE_MAX) {
 125        return -EINVAL;
 126    }
 127    virtio_queue_notify(virtio_ccw_get_vdev(sch), queue);
 128    return 0;
 129
 130}
 131
 132static int virtio_ccw_hcall_early_printk(const uint64_t *args)
 133{
 134    uint64_t mem = args[0];
 135
 136    if (mem < ram_size) {
 137        /* Early printk */
 138        return 0;
 139    }
 140    return -EINVAL;
 141}
 142
 143static void virtio_ccw_register_hcalls(void)
 144{
 145    s390_register_virtio_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY,
 146                                   virtio_ccw_hcall_notify);
 147    /* Tolerate early printk. */
 148    s390_register_virtio_hypercall(KVM_S390_VIRTIO_NOTIFY,
 149                                   virtio_ccw_hcall_early_printk);
 150}
 151
 152/*
 153 * KVM does only support memory slots up to KVM_MEM_MAX_NR_PAGES pages
 154 * as the dirty bitmap must be managed by bitops that take an int as
 155 * position indicator. If we have a guest beyond that we will split off
 156 * new subregions. The split must happen on a segment boundary (1MB).
 157 */
 158#define KVM_MEM_MAX_NR_PAGES ((1ULL << 31) - 1)
 159#define SEG_MSK (~0xfffffULL)
 160#define KVM_SLOT_MAX_BYTES ((KVM_MEM_MAX_NR_PAGES * TARGET_PAGE_SIZE) & SEG_MSK)
 161static void s390_memory_init(ram_addr_t mem_size)
 162{
 163    MemoryRegion *sysmem = get_system_memory();
 164    ram_addr_t chunk, offset = 0;
 165    unsigned int number = 0;
 166    gchar *name;
 167
 168    /* allocate RAM for core */
 169    name = g_strdup_printf("s390.ram");
 170    while (mem_size) {
 171        MemoryRegion *ram = g_new(MemoryRegion, 1);
 172        uint64_t size = mem_size;
 173
 174        /* KVM does not allow memslots >= 8 TB */
 175        chunk = MIN(size, KVM_SLOT_MAX_BYTES);
 176        memory_region_allocate_system_memory(ram, NULL, name, chunk);
 177        memory_region_add_subregion(sysmem, offset, ram);
 178        mem_size -= chunk;
 179        offset += chunk;
 180        g_free(name);
 181        name = g_strdup_printf("s390.ram.%u", ++number);
 182    }
 183    g_free(name);
 184
 185    /* Initialize storage key device */
 186    s390_skeys_init();
 187    /* Initialize storage attributes device */
 188    s390_stattrib_init();
 189}
 190
 191static void s390_init_ipl_dev(const char *kernel_filename,
 192                              const char *kernel_cmdline,
 193                              const char *initrd_filename, const char *firmware,
 194                              const char *netboot_fw, bool enforce_bios)
 195{
 196    Object *new = object_new(TYPE_S390_IPL);
 197    DeviceState *dev = DEVICE(new);
 198    char *netboot_fw_prop;
 199
 200    if (kernel_filename) {
 201        qdev_prop_set_string(dev, "kernel", kernel_filename);
 202    }
 203    if (initrd_filename) {
 204        qdev_prop_set_string(dev, "initrd", initrd_filename);
 205    }
 206    qdev_prop_set_string(dev, "cmdline", kernel_cmdline);
 207    qdev_prop_set_string(dev, "firmware", firmware);
 208    qdev_prop_set_bit(dev, "enforce_bios", enforce_bios);
 209    netboot_fw_prop = object_property_get_str(new, "netboot_fw", &error_abort);
 210    if (!strlen(netboot_fw_prop)) {
 211        qdev_prop_set_string(dev, "netboot_fw", netboot_fw);
 212    }
 213    g_free(netboot_fw_prop);
 214    object_property_add_child(qdev_get_machine(), TYPE_S390_IPL,
 215                              new, NULL);
 216    object_unref(new);
 217    qdev_init_nofail(dev);
 218}
 219
 220static void s390_create_virtio_net(BusState *bus, const char *name)
 221{
 222    int i;
 223
 224    for (i = 0; i < nb_nics; i++) {
 225        NICInfo *nd = &nd_table[i];
 226        DeviceState *dev;
 227
 228        if (!nd->model) {
 229            nd->model = g_strdup("virtio");
 230        }
 231
 232        qemu_check_nic_model(nd, "virtio");
 233
 234        dev = qdev_create(bus, name);
 235        qdev_set_nic_properties(dev, nd);
 236        qdev_init_nofail(dev);
 237    }
 238}
 239
 240static void s390_create_sclpconsole(const char *type, Chardev *chardev)
 241{
 242    DeviceState *dev;
 243
 244    dev = qdev_create(sclp_get_event_facility_bus(), type);
 245    qdev_prop_set_chr(dev, "chardev", chardev);
 246    qdev_init_nofail(dev);
 247}
 248
 249static void ccw_init(MachineState *machine)
 250{
 251    int ret;
 252    VirtualCssBus *css_bus;
 253    DeviceState *dev;
 254
 255    s390_sclp_init();
 256    s390_memory_init(machine->ram_size);
 257
 258    /* init CPUs (incl. CPU model) early so s390_has_feature() works */
 259    s390_init_cpus(machine);
 260
 261    s390_flic_init();
 262
 263    /* init the SIGP facility */
 264    s390_init_sigp();
 265
 266    /* create AP bridge and bus(es) */
 267    s390_init_ap();
 268
 269    /* get a BUS */
 270    css_bus = virtual_css_bus_init();
 271    s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline,
 272                      machine->initrd_filename, "s390-ccw.img",
 273                      "s390-netboot.img", true);
 274
 275    dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE);
 276    object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE,
 277                              OBJECT(dev), NULL);
 278    qdev_init_nofail(dev);
 279
 280    /* register hypercalls */
 281    virtio_ccw_register_hcalls();
 282
 283    s390_enable_css_support(s390_cpu_addr2state(0));
 284
 285    ret = css_create_css_image(VIRTUAL_CSSID, true);
 286
 287    assert(ret == 0);
 288    if (css_migration_enabled()) {
 289        css_register_vmstate();
 290    }
 291
 292    /* Create VirtIO network adapters */
 293    s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw");
 294
 295    /* init consoles */
 296    if (serial_hd(0)) {
 297        s390_create_sclpconsole("sclpconsole", serial_hd(0));
 298    }
 299    if (serial_hd(1)) {
 300        s390_create_sclpconsole("sclplmconsole", serial_hd(1));
 301    }
 302
 303    /* init the TOD clock */
 304    s390_init_tod();
 305}
 306
 307static void s390_cpu_plug(HotplugHandler *hotplug_dev,
 308                        DeviceState *dev, Error **errp)
 309{
 310    MachineState *ms = MACHINE(hotplug_dev);
 311    S390CPU *cpu = S390_CPU(dev);
 312
 313    g_assert(!ms->possible_cpus->cpus[cpu->env.core_id].cpu);
 314    ms->possible_cpus->cpus[cpu->env.core_id].cpu = OBJECT(dev);
 315
 316    if (dev->hotplugged) {
 317        raise_irq_cpu_hotplug();
 318    }
 319}
 320
 321static inline void s390_do_cpu_ipl(CPUState *cs, run_on_cpu_data arg)
 322{
 323    S390CPU *cpu = S390_CPU(cs);
 324
 325    s390_ipl_prepare_cpu(cpu);
 326    s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
 327}
 328
 329static void s390_machine_reset(void)
 330{
 331    enum s390_reset reset_type;
 332    CPUState *cs, *t;
 333
 334    /* get the reset parameters, reset them once done */
 335    s390_ipl_get_reset_request(&cs, &reset_type);
 336
 337    /* all CPUs are paused and synchronized at this point */
 338    s390_cmma_reset();
 339
 340    switch (reset_type) {
 341    case S390_RESET_EXTERNAL:
 342    case S390_RESET_REIPL:
 343        qemu_devices_reset();
 344        s390_crypto_reset();
 345
 346        /* configure and start the ipl CPU only */
 347        run_on_cpu(cs, s390_do_cpu_ipl, RUN_ON_CPU_NULL);
 348        break;
 349    case S390_RESET_MODIFIED_CLEAR:
 350        CPU_FOREACH(t) {
 351            run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL);
 352        }
 353        subsystem_reset();
 354        s390_crypto_reset();
 355        run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL);
 356        break;
 357    case S390_RESET_LOAD_NORMAL:
 358        CPU_FOREACH(t) {
 359            run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL);
 360        }
 361        subsystem_reset();
 362        run_on_cpu(cs, s390_do_cpu_initial_reset, RUN_ON_CPU_NULL);
 363        run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL);
 364        break;
 365    default:
 366        g_assert_not_reached();
 367    }
 368    s390_ipl_clear_reset_request();
 369}
 370
 371static void s390_machine_device_plug(HotplugHandler *hotplug_dev,
 372                                     DeviceState *dev, Error **errp)
 373{
 374    if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
 375        s390_cpu_plug(hotplug_dev, dev, errp);
 376    }
 377}
 378
 379static void s390_machine_device_unplug_request(HotplugHandler *hotplug_dev,
 380                                               DeviceState *dev, Error **errp)
 381{
 382    if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
 383        error_setg(errp, "CPU hot unplug not supported on this machine");
 384        return;
 385    }
 386}
 387
 388static CpuInstanceProperties s390_cpu_index_to_props(MachineState *ms,
 389                                                     unsigned cpu_index)
 390{
 391    MachineClass *mc = MACHINE_GET_CLASS(ms);
 392    const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
 393
 394    assert(cpu_index < possible_cpus->len);
 395    return possible_cpus->cpus[cpu_index].props;
 396}
 397
 398static const CPUArchIdList *s390_possible_cpu_arch_ids(MachineState *ms)
 399{
 400    int i;
 401
 402    if (ms->possible_cpus) {
 403        g_assert(ms->possible_cpus && ms->possible_cpus->len == max_cpus);
 404        return ms->possible_cpus;
 405    }
 406
 407    ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
 408                                  sizeof(CPUArchId) * max_cpus);
 409    ms->possible_cpus->len = max_cpus;
 410    for (i = 0; i < ms->possible_cpus->len; i++) {
 411        ms->possible_cpus->cpus[i].type = ms->cpu_type;
 412        ms->possible_cpus->cpus[i].vcpus_count = 1;
 413        ms->possible_cpus->cpus[i].arch_id = i;
 414        ms->possible_cpus->cpus[i].props.has_core_id = true;
 415        ms->possible_cpus->cpus[i].props.core_id = i;
 416    }
 417
 418    return ms->possible_cpus;
 419}
 420
 421static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
 422                                                DeviceState *dev)
 423{
 424    if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
 425        return HOTPLUG_HANDLER(machine);
 426    }
 427    return NULL;
 428}
 429
 430static void s390_hot_add_cpu(const int64_t id, Error **errp)
 431{
 432    MachineState *machine = MACHINE(qdev_get_machine());
 433    ObjectClass *oc;
 434
 435    g_assert(machine->possible_cpus->cpus[0].cpu);
 436    oc = OBJECT_CLASS(CPU_GET_CLASS(machine->possible_cpus->cpus[0].cpu));
 437
 438    s390x_new_cpu(object_class_get_name(oc), id, errp);
 439}
 440
 441static void s390_nmi(NMIState *n, int cpu_index, Error **errp)
 442{
 443    CPUState *cs = qemu_get_cpu(cpu_index);
 444
 445    s390_cpu_restart(S390_CPU(cs));
 446}
 447
 448static void ccw_machine_class_init(ObjectClass *oc, void *data)
 449{
 450    MachineClass *mc = MACHINE_CLASS(oc);
 451    NMIClass *nc = NMI_CLASS(oc);
 452    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
 453    S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
 454
 455    s390mc->ri_allowed = true;
 456    s390mc->cpu_model_allowed = true;
 457    s390mc->css_migration_enabled = true;
 458    s390mc->hpage_1m_allowed = true;
 459    mc->init = ccw_init;
 460    mc->reset = s390_machine_reset;
 461    mc->hot_add_cpu = s390_hot_add_cpu;
 462    mc->block_default_type = IF_VIRTIO;
 463    mc->no_cdrom = 1;
 464    mc->no_floppy = 1;
 465    mc->no_parallel = 1;
 466    mc->no_sdcard = 1;
 467    mc->max_cpus = S390_MAX_CPUS;
 468    mc->has_hotpluggable_cpus = true;
 469    assert(!mc->get_hotplug_handler);
 470    mc->get_hotplug_handler = s390_get_hotplug_handler;
 471    mc->cpu_index_to_instance_props = s390_cpu_index_to_props;
 472    mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids;
 473    /* it is overridden with 'host' cpu *in kvm_arch_init* */
 474    mc->default_cpu_type = S390_CPU_TYPE_NAME("qemu");
 475    hc->plug = s390_machine_device_plug;
 476    hc->unplug_request = s390_machine_device_unplug_request;
 477    nc->nmi_monitor_handler = s390_nmi;
 478}
 479
 480static inline bool machine_get_aes_key_wrap(Object *obj, Error **errp)
 481{
 482    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
 483
 484    return ms->aes_key_wrap;
 485}
 486
 487static inline void machine_set_aes_key_wrap(Object *obj, bool value,
 488                                            Error **errp)
 489{
 490    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
 491
 492    ms->aes_key_wrap = value;
 493}
 494
 495static inline bool machine_get_dea_key_wrap(Object *obj, Error **errp)
 496{
 497    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
 498
 499    return ms->dea_key_wrap;
 500}
 501
 502static inline void machine_set_dea_key_wrap(Object *obj, bool value,
 503                                            Error **errp)
 504{
 505    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
 506
 507    ms->dea_key_wrap = value;
 508}
 509
 510static S390CcwMachineClass *current_mc;
 511
 512static S390CcwMachineClass *get_machine_class(void)
 513{
 514    if (unlikely(!current_mc)) {
 515        /*
 516        * No s390 ccw machine was instantiated, we are likely to
 517        * be called for the 'none' machine. The properties will
 518        * have their after-initialization values.
 519        */
 520        current_mc = S390_MACHINE_CLASS(
 521                     object_class_by_name(TYPE_S390_CCW_MACHINE));
 522    }
 523    return current_mc;
 524}
 525
 526bool ri_allowed(void)
 527{
 528    /* for "none" machine this results in true */
 529    return get_machine_class()->ri_allowed;
 530}
 531
 532bool cpu_model_allowed(void)
 533{
 534    /* for "none" machine this results in true */
 535    return get_machine_class()->cpu_model_allowed;
 536}
 537
 538bool hpage_1m_allowed(void)
 539{
 540    /* for "none" machine this results in true */
 541    return get_machine_class()->hpage_1m_allowed;
 542}
 543
 544static char *machine_get_loadparm(Object *obj, Error **errp)
 545{
 546    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
 547
 548    return g_memdup(ms->loadparm, sizeof(ms->loadparm));
 549}
 550
 551static void machine_set_loadparm(Object *obj, const char *val, Error **errp)
 552{
 553    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
 554    int i;
 555
 556    for (i = 0; i < sizeof(ms->loadparm) && val[i]; i++) {
 557        uint8_t c = qemu_toupper(val[i]); /* mimic HMC */
 558
 559        if (('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || (c == '.') ||
 560            (c == ' ')) {
 561            ms->loadparm[i] = c;
 562        } else {
 563            error_setg(errp, "LOADPARM: invalid character '%c' (ASCII 0x%02x)",
 564                       c, c);
 565            return;
 566        }
 567    }
 568
 569    for (; i < sizeof(ms->loadparm); i++) {
 570        ms->loadparm[i] = ' '; /* pad right with spaces */
 571    }
 572}
 573static inline void s390_machine_initfn(Object *obj)
 574{
 575    object_property_add_bool(obj, "aes-key-wrap",
 576                             machine_get_aes_key_wrap,
 577                             machine_set_aes_key_wrap, NULL);
 578    object_property_set_description(obj, "aes-key-wrap",
 579            "enable/disable AES key wrapping using the CPACF wrapping key",
 580            NULL);
 581    object_property_set_bool(obj, true, "aes-key-wrap", NULL);
 582
 583    object_property_add_bool(obj, "dea-key-wrap",
 584                             machine_get_dea_key_wrap,
 585                             machine_set_dea_key_wrap, NULL);
 586    object_property_set_description(obj, "dea-key-wrap",
 587            "enable/disable DEA key wrapping using the CPACF wrapping key",
 588            NULL);
 589    object_property_set_bool(obj, true, "dea-key-wrap", NULL);
 590    object_property_add_str(obj, "loadparm",
 591            machine_get_loadparm, machine_set_loadparm, NULL);
 592    object_property_set_description(obj, "loadparm",
 593            "Up to 8 chars in set of [A-Za-z0-9. ] (lower case chars converted"
 594            " to upper case) to pass to machine loader, boot manager,"
 595            " and guest kernel",
 596            NULL);
 597}
 598
 599static const TypeInfo ccw_machine_info = {
 600    .name          = TYPE_S390_CCW_MACHINE,
 601    .parent        = TYPE_MACHINE,
 602    .abstract      = true,
 603    .instance_size = sizeof(S390CcwMachineState),
 604    .instance_init = s390_machine_initfn,
 605    .class_size = sizeof(S390CcwMachineClass),
 606    .class_init    = ccw_machine_class_init,
 607    .interfaces = (InterfaceInfo[]) {
 608        { TYPE_NMI },
 609        { TYPE_HOTPLUG_HANDLER},
 610        { }
 611    },
 612};
 613
 614bool css_migration_enabled(void)
 615{
 616    return get_machine_class()->css_migration_enabled;
 617}
 618
 619#define DEFINE_CCW_MACHINE(suffix, verstr, latest)                            \
 620    static void ccw_machine_##suffix##_class_init(ObjectClass *oc,            \
 621                                                  void *data)                 \
 622    {                                                                         \
 623        MachineClass *mc = MACHINE_CLASS(oc);                                 \
 624        ccw_machine_##suffix##_class_options(mc);                             \
 625        mc->desc = "VirtIO-ccw based S390 machine v" verstr;                  \
 626        if (latest) {                                                         \
 627            mc->alias = "s390-ccw-virtio";                                    \
 628            mc->is_default = 1;                                               \
 629        }                                                                     \
 630    }                                                                         \
 631    static void ccw_machine_##suffix##_instance_init(Object *obj)             \
 632    {                                                                         \
 633        MachineState *machine = MACHINE(obj);                                 \
 634        current_mc = S390_MACHINE_CLASS(MACHINE_GET_CLASS(machine));          \
 635        ccw_machine_##suffix##_instance_options(machine);                     \
 636    }                                                                         \
 637    static const TypeInfo ccw_machine_##suffix##_info = {                     \
 638        .name = MACHINE_TYPE_NAME("s390-ccw-virtio-" verstr),                 \
 639        .parent = TYPE_S390_CCW_MACHINE,                                      \
 640        .class_init = ccw_machine_##suffix##_class_init,                      \
 641        .instance_init = ccw_machine_##suffix##_instance_init,                \
 642    };                                                                        \
 643    static void ccw_machine_register_##suffix(void)                           \
 644    {                                                                         \
 645        type_register_static(&ccw_machine_##suffix##_info);                   \
 646    }                                                                         \
 647    type_init(ccw_machine_register_##suffix)
 648
 649static void ccw_machine_4_0_instance_options(MachineState *machine)
 650{
 651}
 652
 653static void ccw_machine_4_0_class_options(MachineClass *mc)
 654{
 655}
 656DEFINE_CCW_MACHINE(4_0, "4.0", true);
 657
 658static void ccw_machine_3_1_instance_options(MachineState *machine)
 659{
 660    static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V3_1 };
 661    ccw_machine_4_0_instance_options(machine);
 662    s390_cpudef_featoff_greater(14, 1, S390_FEAT_MULTIPLE_EPOCH);
 663    s390_cpudef_group_featoff_greater(14, 1, S390_FEAT_GROUP_MULTIPLE_EPOCH_PTFF);
 664    s390_set_qemu_cpu_model(0x2827, 12, 2, qemu_cpu_feat);
 665}
 666
 667static void ccw_machine_3_1_class_options(MachineClass *mc)
 668{
 669    ccw_machine_4_0_class_options(mc);
 670    compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len);
 671}
 672DEFINE_CCW_MACHINE(3_1, "3.1", false);
 673
 674static void ccw_machine_3_0_instance_options(MachineState *machine)
 675{
 676    ccw_machine_3_1_instance_options(machine);
 677}
 678
 679static void ccw_machine_3_0_class_options(MachineClass *mc)
 680{
 681    S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
 682
 683    s390mc->hpage_1m_allowed = false;
 684    ccw_machine_3_1_class_options(mc);
 685    compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len);
 686}
 687DEFINE_CCW_MACHINE(3_0, "3.0", false);
 688
 689static void ccw_machine_2_12_instance_options(MachineState *machine)
 690{
 691    ccw_machine_3_0_instance_options(machine);
 692    s390_cpudef_featoff_greater(11, 1, S390_FEAT_PPA15);
 693    s390_cpudef_featoff_greater(11, 1, S390_FEAT_BPB);
 694}
 695
 696static void ccw_machine_2_12_class_options(MachineClass *mc)
 697{
 698    ccw_machine_3_0_class_options(mc);
 699    compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len);
 700}
 701DEFINE_CCW_MACHINE(2_12, "2.12", false);
 702
 703static void ccw_machine_2_11_instance_options(MachineState *machine)
 704{
 705    static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V2_11 };
 706    ccw_machine_2_12_instance_options(machine);
 707
 708    /* before 2.12 we emulated the very first z900 */
 709    s390_set_qemu_cpu_model(0x2064, 7, 1, qemu_cpu_feat);
 710}
 711
 712static void ccw_machine_2_11_class_options(MachineClass *mc)
 713{
 714    static GlobalProperty compat[] = {
 715        { TYPE_SCLP_EVENT_FACILITY, "allow_all_mask_sizes", "off", },
 716    };
 717
 718    ccw_machine_2_12_class_options(mc);
 719    compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len);
 720    compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
 721}
 722DEFINE_CCW_MACHINE(2_11, "2.11", false);
 723
 724static void ccw_machine_2_10_instance_options(MachineState *machine)
 725{
 726    ccw_machine_2_11_instance_options(machine);
 727}
 728
 729static void ccw_machine_2_10_class_options(MachineClass *mc)
 730{
 731    ccw_machine_2_11_class_options(mc);
 732    compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len);
 733}
 734DEFINE_CCW_MACHINE(2_10, "2.10", false);
 735
 736static void ccw_machine_2_9_instance_options(MachineState *machine)
 737{
 738    ccw_machine_2_10_instance_options(machine);
 739    s390_cpudef_featoff_greater(12, 1, S390_FEAT_ESOP);
 740    s390_cpudef_featoff_greater(12, 1, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2);
 741    s390_cpudef_featoff_greater(12, 1, S390_FEAT_ZPCI);
 742    s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_INT_SUPPRESSION);
 743    s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_EVENT_NOTIFICATION);
 744}
 745
 746static void ccw_machine_2_9_class_options(MachineClass *mc)
 747{
 748    S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
 749    static GlobalProperty compat[] = {
 750        { TYPE_S390_STATTRIB, "migration-enabled", "off", },
 751    };
 752
 753    ccw_machine_2_10_class_options(mc);
 754    compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len);
 755    compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
 756    s390mc->css_migration_enabled = false;
 757}
 758DEFINE_CCW_MACHINE(2_9, "2.9", false);
 759
 760static void ccw_machine_2_8_instance_options(MachineState *machine)
 761{
 762    ccw_machine_2_9_instance_options(machine);
 763}
 764
 765static void ccw_machine_2_8_class_options(MachineClass *mc)
 766{
 767    static GlobalProperty compat[] = {
 768        { TYPE_S390_FLIC_COMMON, "adapter_routes_max_batch", "64", },
 769    };
 770
 771    ccw_machine_2_9_class_options(mc);
 772    compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len);
 773    compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
 774}
 775DEFINE_CCW_MACHINE(2_8, "2.8", false);
 776
 777static void ccw_machine_2_7_instance_options(MachineState *machine)
 778{
 779    ccw_machine_2_8_instance_options(machine);
 780}
 781
 782static void ccw_machine_2_7_class_options(MachineClass *mc)
 783{
 784    S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
 785
 786    s390mc->cpu_model_allowed = false;
 787    ccw_machine_2_8_class_options(mc);
 788    compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len);
 789}
 790DEFINE_CCW_MACHINE(2_7, "2.7", false);
 791
 792static void ccw_machine_2_6_instance_options(MachineState *machine)
 793{
 794    ccw_machine_2_7_instance_options(machine);
 795}
 796
 797static void ccw_machine_2_6_class_options(MachineClass *mc)
 798{
 799    S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
 800    static GlobalProperty compat[] = {
 801        { TYPE_S390_IPL, "iplbext_migration", "off", },
 802         { TYPE_VIRTUAL_CSS_BRIDGE, "css_dev_path", "off", },
 803    };
 804
 805    s390mc->ri_allowed = false;
 806    ccw_machine_2_7_class_options(mc);
 807    compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len);
 808    compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
 809}
 810DEFINE_CCW_MACHINE(2_6, "2.6", false);
 811
 812static void ccw_machine_2_5_instance_options(MachineState *machine)
 813{
 814    ccw_machine_2_6_instance_options(machine);
 815}
 816
 817static void ccw_machine_2_5_class_options(MachineClass *mc)
 818{
 819    ccw_machine_2_6_class_options(mc);
 820    compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len);
 821}
 822DEFINE_CCW_MACHINE(2_5, "2.5", false);
 823
 824static void ccw_machine_2_4_instance_options(MachineState *machine)
 825{
 826    ccw_machine_2_5_instance_options(machine);
 827}
 828
 829static void ccw_machine_2_4_class_options(MachineClass *mc)
 830{
 831    static GlobalProperty compat[] = {
 832        { TYPE_S390_SKEYS, "migration-enabled", "off", },
 833        { "virtio-blk-ccw", "max_revision", "0", },
 834        { "virtio-balloon-ccw", "max_revision", "0", },
 835        { "virtio-serial-ccw", "max_revision", "0", },
 836        { "virtio-9p-ccw", "max_revision", "0", },
 837        { "virtio-rng-ccw", "max_revision", "0", },
 838        { "virtio-net-ccw", "max_revision", "0", },
 839        { "virtio-scsi-ccw", "max_revision", "0", },
 840        { "vhost-scsi-ccw", "max_revision", "0", },
 841    };
 842
 843    ccw_machine_2_5_class_options(mc);
 844    compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len);
 845    compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
 846}
 847DEFINE_CCW_MACHINE(2_4, "2.4", false);
 848
 849static void ccw_machine_register_types(void)
 850{
 851    type_register_static(&ccw_machine_info);
 852}
 853
 854type_init(ccw_machine_register_types)
 855