xref: /qemu/hw/s390x/s390-virtio-ccw.c (revision 940bb5fa)
1 /*
2  * virtio ccw machine
3  *
4  * Copyright 2012, 2020 IBM Corp.
5  * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
6  * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
7  *            Janosch Frank <frankja@linux.ibm.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or (at
10  * your option) any later version. See the COPYING file in the top-level
11  * directory.
12  */
13 
14 #include "qemu/osdep.h"
15 #include "qapi/error.h"
16 #include "exec/ram_addr.h"
17 #include "hw/s390x/s390-virtio-hcall.h"
18 #include "hw/s390x/sclp.h"
19 #include "hw/s390x/s390_flic.h"
20 #include "hw/s390x/ioinst.h"
21 #include "hw/s390x/css.h"
22 #include "virtio-ccw.h"
23 #include "qemu/config-file.h"
24 #include "qemu/ctype.h"
25 #include "qemu/error-report.h"
26 #include "qemu/option.h"
27 #include "qemu/qemu-print.h"
28 #include "qemu/units.h"
29 #include "hw/s390x/s390-pci-bus.h"
30 #include "sysemu/reset.h"
31 #include "hw/s390x/storage-keys.h"
32 #include "hw/s390x/storage-attributes.h"
33 #include "hw/s390x/event-facility.h"
34 #include "ipl.h"
35 #include "hw/s390x/s390-virtio-ccw.h"
36 #include "hw/s390x/css-bridge.h"
37 #include "hw/s390x/ap-bridge.h"
38 #include "migration/register.h"
39 #include "cpu_models.h"
40 #include "hw/nmi.h"
41 #include "hw/qdev-properties.h"
42 #include "hw/s390x/tod.h"
43 #include "sysemu/sysemu.h"
44 #include "sysemu/cpus.h"
45 #include "target/s390x/kvm/pv.h"
46 #include "migration/blocker.h"
47 #include "qapi/visitor.h"
48 #include "hw/s390x/cpu-topology.h"
49 
50 static Error *pv_mig_blocker;
51 
52 S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
53 {
54     static MachineState *ms;
55 
56     if (!ms) {
57         ms = MACHINE(qdev_get_machine());
58         g_assert(ms->possible_cpus);
59     }
60 
61     /* CPU address corresponds to the core_id and the index */
62     if (cpu_addr >= ms->possible_cpus->len) {
63         return NULL;
64     }
65     return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
66 }
67 
68 static S390CPU *s390x_new_cpu(const char *typename, uint32_t core_id,
69                               Error **errp)
70 {
71     S390CPU *cpu = S390_CPU(object_new(typename));
72     S390CPU *ret = NULL;
73 
74     if (!object_property_set_int(OBJECT(cpu), "core-id", core_id, errp)) {
75         goto out;
76     }
77     if (!qdev_realize(DEVICE(cpu), NULL, errp)) {
78         goto out;
79     }
80     ret = cpu;
81 
82 out:
83     object_unref(OBJECT(cpu));
84     return ret;
85 }
86 
87 static void s390_init_cpus(MachineState *machine)
88 {
89     MachineClass *mc = MACHINE_GET_CLASS(machine);
90     S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
91     int i;
92 
93     if (machine->smp.threads > s390mc->max_threads) {
94         error_report("S390 does not support more than %d threads.",
95                      s390mc->max_threads);
96         exit(1);
97     }
98 
99     /* initialize possible_cpus */
100     mc->possible_cpu_arch_ids(machine);
101 
102     for (i = 0; i < machine->smp.cpus; i++) {
103         s390x_new_cpu(machine->cpu_type, i, &error_fatal);
104     }
105 }
106 
107 static const char *const reset_dev_types[] = {
108     TYPE_VIRTUAL_CSS_BRIDGE,
109     "s390-sclp-event-facility",
110     "s390-flic",
111     "diag288",
112     TYPE_S390_PCI_HOST_BRIDGE,
113     TYPE_AP_BRIDGE,
114 };
115 
116 static void subsystem_reset(void)
117 {
118     DeviceState *dev;
119     int i;
120 
121     for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) {
122         dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL));
123         if (dev) {
124             device_cold_reset(dev);
125         }
126     }
127     if (s390_has_topology()) {
128         s390_topology_reset();
129     }
130 }
131 
132 static int virtio_ccw_hcall_notify(const uint64_t *args)
133 {
134     uint64_t subch_id = args[0];
135     uint64_t queue = args[1];
136     SubchDev *sch;
137     int cssid, ssid, schid, m;
138 
139     if (ioinst_disassemble_sch_ident(subch_id, &m, &cssid, &ssid, &schid)) {
140         return -EINVAL;
141     }
142     sch = css_find_subch(m, cssid, ssid, schid);
143     if (!sch || !css_subch_visible(sch)) {
144         return -EINVAL;
145     }
146     if (queue >= VIRTIO_QUEUE_MAX) {
147         return -EINVAL;
148     }
149     virtio_queue_notify(virtio_ccw_get_vdev(sch), queue);
150     return 0;
151 
152 }
153 
154 static int virtio_ccw_hcall_early_printk(const uint64_t *args)
155 {
156     uint64_t mem = args[0];
157     MachineState *ms = MACHINE(qdev_get_machine());
158 
159     if (mem < ms->ram_size) {
160         /* Early printk */
161         return 0;
162     }
163     return -EINVAL;
164 }
165 
166 static void virtio_ccw_register_hcalls(void)
167 {
168     s390_register_virtio_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY,
169                                    virtio_ccw_hcall_notify);
170     /* Tolerate early printk. */
171     s390_register_virtio_hypercall(KVM_S390_VIRTIO_NOTIFY,
172                                    virtio_ccw_hcall_early_printk);
173 }
174 
175 static void s390_memory_init(MemoryRegion *ram)
176 {
177     MemoryRegion *sysmem = get_system_memory();
178 
179     /* allocate RAM for core */
180     memory_region_add_subregion(sysmem, 0, ram);
181 
182     /*
183      * Configure the maximum page size. As no memory devices were created
184      * yet, this is the page size of initial memory only.
185      */
186     s390_set_max_pagesize(qemu_maxrampagesize(), &error_fatal);
187     /* Initialize storage key device */
188     s390_skeys_init();
189     /* Initialize storage attributes device */
190     s390_stattrib_init();
191 }
192 
193 static void s390_init_ipl_dev(const char *kernel_filename,
194                               const char *kernel_cmdline,
195                               const char *initrd_filename, const char *firmware,
196                               const char *netboot_fw, bool enforce_bios)
197 {
198     Object *new = object_new(TYPE_S390_IPL);
199     DeviceState *dev = DEVICE(new);
200     char *netboot_fw_prop;
201 
202     if (kernel_filename) {
203         qdev_prop_set_string(dev, "kernel", kernel_filename);
204     }
205     if (initrd_filename) {
206         qdev_prop_set_string(dev, "initrd", initrd_filename);
207     }
208     qdev_prop_set_string(dev, "cmdline", kernel_cmdline);
209     qdev_prop_set_string(dev, "firmware", firmware);
210     qdev_prop_set_bit(dev, "enforce_bios", enforce_bios);
211     netboot_fw_prop = object_property_get_str(new, "netboot_fw", &error_abort);
212     if (!strlen(netboot_fw_prop)) {
213         qdev_prop_set_string(dev, "netboot_fw", netboot_fw);
214     }
215     g_free(netboot_fw_prop);
216     object_property_add_child(qdev_get_machine(), TYPE_S390_IPL,
217                               new);
218     object_unref(new);
219     qdev_realize(dev, NULL, &error_fatal);
220 }
221 
222 static void s390_create_virtio_net(BusState *bus, const char *name)
223 {
224     int i;
225 
226     for (i = 0; i < nb_nics; i++) {
227         NICInfo *nd = &nd_table[i];
228         DeviceState *dev;
229 
230         qemu_check_nic_model(nd, "virtio");
231 
232         dev = qdev_new(name);
233         qdev_set_nic_properties(dev, nd);
234         qdev_realize_and_unref(dev, bus, &error_fatal);
235     }
236 }
237 
238 static void s390_create_sclpconsole(const char *type, Chardev *chardev)
239 {
240     DeviceState *dev;
241 
242     dev = qdev_new(type);
243     qdev_prop_set_chr(dev, "chardev", chardev);
244     qdev_realize_and_unref(dev, sclp_get_event_facility_bus(), &error_fatal);
245 }
246 
247 static void ccw_init(MachineState *machine)
248 {
249     MachineClass *mc = MACHINE_GET_CLASS(machine);
250     int ret;
251     VirtualCssBus *css_bus;
252     DeviceState *dev;
253 
254     s390_sclp_init();
255     /* init memory + setup max page size. Required for the CPU model */
256     s390_memory_init(machine->ram);
257 
258     /* init CPUs (incl. CPU model) early so s390_has_feature() works */
259     s390_init_cpus(machine);
260 
261     /* Need CPU model to be determined before we can set up PV */
262     s390_pv_init(machine->cgs, &error_fatal);
263 
264     s390_flic_init();
265 
266     /* init the SIGP facility */
267     s390_init_sigp();
268 
269     /* create AP bridge and bus(es) */
270     s390_init_ap();
271 
272     /* get a BUS */
273     css_bus = virtual_css_bus_init();
274     s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline,
275                       machine->initrd_filename,
276                       machine->firmware ?: "s390-ccw.img",
277                       "s390-netboot.img", true);
278 
279     dev = qdev_new(TYPE_S390_PCI_HOST_BRIDGE);
280     object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE,
281                               OBJECT(dev));
282     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
283 
284     /* register hypercalls */
285     virtio_ccw_register_hcalls();
286 
287     s390_enable_css_support(s390_cpu_addr2state(0));
288 
289     ret = css_create_css_image(VIRTUAL_CSSID, true);
290 
291     assert(ret == 0);
292     if (css_migration_enabled()) {
293         css_register_vmstate();
294     }
295 
296     /* Create VirtIO network adapters */
297     s390_create_virtio_net(BUS(css_bus), mc->default_nic);
298 
299     /* init consoles */
300     if (serial_hd(0)) {
301         s390_create_sclpconsole("sclpconsole", serial_hd(0));
302     }
303     if (serial_hd(1)) {
304         s390_create_sclpconsole("sclplmconsole", serial_hd(1));
305     }
306 
307     /* init the TOD clock */
308     s390_init_tod();
309 }
310 
311 static void s390_cpu_plug(HotplugHandler *hotplug_dev,
312                         DeviceState *dev, Error **errp)
313 {
314     MachineState *ms = MACHINE(hotplug_dev);
315     S390CPU *cpu = S390_CPU(dev);
316     ERRP_GUARD();
317 
318     g_assert(!ms->possible_cpus->cpus[cpu->env.core_id].cpu);
319     ms->possible_cpus->cpus[cpu->env.core_id].cpu = OBJECT(dev);
320 
321     if (s390_has_topology()) {
322         s390_topology_setup_cpu(ms, cpu, errp);
323         if (*errp) {
324             return;
325         }
326     }
327 
328     if (dev->hotplugged) {
329         raise_irq_cpu_hotplug();
330     }
331 }
332 
333 static inline void s390_do_cpu_ipl(CPUState *cs, run_on_cpu_data arg)
334 {
335     S390CPU *cpu = S390_CPU(cs);
336 
337     s390_ipl_prepare_cpu(cpu);
338     s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
339 }
340 
341 static void s390_machine_unprotect(S390CcwMachineState *ms)
342 {
343     if (!s390_pv_vm_try_disable_async(ms)) {
344         s390_pv_vm_disable();
345     }
346     ms->pv = false;
347     migrate_del_blocker(&pv_mig_blocker);
348     ram_block_discard_disable(false);
349 }
350 
351 static int s390_machine_protect(S390CcwMachineState *ms)
352 {
353     Error *local_err = NULL;
354     int rc;
355 
356    /*
357     * Discarding of memory in RAM blocks does not work as expected with
358     * protected VMs. Sharing and unsharing pages would be required. Disable
359     * it for now, until until we have a solution to make at least Linux
360     * guests either support it (e.g., virtio-balloon) or fail gracefully.
361     */
362     rc = ram_block_discard_disable(true);
363     if (rc) {
364         error_report("protected VMs: cannot disable RAM discard");
365         return rc;
366     }
367 
368     error_setg(&pv_mig_blocker,
369                "protected VMs are currently not migratable.");
370     rc = migrate_add_blocker(&pv_mig_blocker, &local_err);
371     if (rc) {
372         ram_block_discard_disable(false);
373         error_report_err(local_err);
374         return rc;
375     }
376 
377     /* Create SE VM */
378     rc = s390_pv_vm_enable();
379     if (rc) {
380         ram_block_discard_disable(false);
381         migrate_del_blocker(&pv_mig_blocker);
382         return rc;
383     }
384 
385     ms->pv = true;
386 
387     /* Will return 0 if API is not available since it's not vital */
388     rc = s390_pv_query_info();
389     if (rc) {
390         goto out_err;
391     }
392 
393     /* Set SE header and unpack */
394     rc = s390_ipl_prepare_pv_header();
395     if (rc) {
396         goto out_err;
397     }
398 
399     /* Decrypt image */
400     rc = s390_ipl_pv_unpack();
401     if (rc) {
402         goto out_err;
403     }
404 
405     /* Verify integrity */
406     rc = s390_pv_verify();
407     if (rc) {
408         goto out_err;
409     }
410     return rc;
411 
412 out_err:
413     s390_machine_unprotect(ms);
414     return rc;
415 }
416 
417 static void s390_pv_prepare_reset(S390CcwMachineState *ms)
418 {
419     CPUState *cs;
420 
421     if (!s390_is_pv()) {
422         return;
423     }
424     /* Unsharing requires all cpus to be stopped */
425     CPU_FOREACH(cs) {
426         s390_cpu_set_state(S390_CPU_STATE_STOPPED, S390_CPU(cs));
427     }
428     s390_pv_unshare();
429     s390_pv_prep_reset();
430 }
431 
432 static void s390_machine_reset(MachineState *machine, ShutdownCause reason)
433 {
434     S390CcwMachineState *ms = S390_CCW_MACHINE(machine);
435     enum s390_reset reset_type;
436     CPUState *cs, *t;
437     S390CPU *cpu;
438 
439     /* get the reset parameters, reset them once done */
440     s390_ipl_get_reset_request(&cs, &reset_type);
441 
442     /* all CPUs are paused and synchronized at this point */
443     s390_cmma_reset();
444 
445     cpu = S390_CPU(cs);
446 
447     switch (reset_type) {
448     case S390_RESET_EXTERNAL:
449     case S390_RESET_REIPL:
450         /*
451          * Reset the subsystem which includes a AP reset. If a PV
452          * guest had APQNs attached the AP reset is a prerequisite to
453          * unprotecting since the UV checks if all APQNs are reset.
454          */
455         subsystem_reset();
456         if (s390_is_pv()) {
457             s390_machine_unprotect(ms);
458         }
459 
460         /*
461          * Device reset includes CPU clear resets so this has to be
462          * done AFTER the unprotect call above.
463          */
464         qemu_devices_reset(reason);
465         s390_crypto_reset();
466 
467         /* configure and start the ipl CPU only */
468         run_on_cpu(cs, s390_do_cpu_ipl, RUN_ON_CPU_NULL);
469         break;
470     case S390_RESET_MODIFIED_CLEAR:
471         /*
472          * Subsystem reset needs to be done before we unshare memory
473          * and lose access to VIRTIO structures in guest memory.
474          */
475         subsystem_reset();
476         s390_crypto_reset();
477         s390_pv_prepare_reset(ms);
478         CPU_FOREACH(t) {
479             run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL);
480         }
481         run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL);
482         break;
483     case S390_RESET_LOAD_NORMAL:
484         /*
485          * Subsystem reset needs to be done before we unshare memory
486          * and lose access to VIRTIO structures in guest memory.
487          */
488         subsystem_reset();
489         s390_pv_prepare_reset(ms);
490         CPU_FOREACH(t) {
491             if (t == cs) {
492                 continue;
493             }
494             run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL);
495         }
496         run_on_cpu(cs, s390_do_cpu_initial_reset, RUN_ON_CPU_NULL);
497         run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL);
498         break;
499     case S390_RESET_PV: /* Subcode 10 */
500         subsystem_reset();
501         s390_crypto_reset();
502 
503         CPU_FOREACH(t) {
504             if (t == cs) {
505                 continue;
506             }
507             run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL);
508         }
509         run_on_cpu(cs, s390_do_cpu_reset, RUN_ON_CPU_NULL);
510 
511         if (s390_machine_protect(ms)) {
512             s390_pv_inject_reset_error(cs);
513             /*
514              * Continue after the diag308 so the guest knows something
515              * went wrong.
516              */
517             s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
518             return;
519         }
520 
521         run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL);
522         break;
523     default:
524         g_assert_not_reached();
525     }
526 
527     CPU_FOREACH(t) {
528         run_on_cpu(t, s390_do_cpu_set_diag318, RUN_ON_CPU_HOST_ULONG(0));
529     }
530     s390_ipl_clear_reset_request();
531 }
532 
533 static void s390_machine_device_plug(HotplugHandler *hotplug_dev,
534                                      DeviceState *dev, Error **errp)
535 {
536     if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
537         s390_cpu_plug(hotplug_dev, dev, errp);
538     }
539 }
540 
541 static void s390_machine_device_unplug_request(HotplugHandler *hotplug_dev,
542                                                DeviceState *dev, Error **errp)
543 {
544     if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
545         error_setg(errp, "CPU hot unplug not supported on this machine");
546         return;
547     }
548 }
549 
550 static CpuInstanceProperties s390_cpu_index_to_props(MachineState *ms,
551                                                      unsigned cpu_index)
552 {
553     MachineClass *mc = MACHINE_GET_CLASS(ms);
554     const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
555 
556     assert(cpu_index < possible_cpus->len);
557     return possible_cpus->cpus[cpu_index].props;
558 }
559 
560 static const CPUArchIdList *s390_possible_cpu_arch_ids(MachineState *ms)
561 {
562     int i;
563     unsigned int max_cpus = ms->smp.max_cpus;
564 
565     if (ms->possible_cpus) {
566         g_assert(ms->possible_cpus && ms->possible_cpus->len == max_cpus);
567         return ms->possible_cpus;
568     }
569 
570     ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
571                                   sizeof(CPUArchId) * max_cpus);
572     ms->possible_cpus->len = max_cpus;
573     for (i = 0; i < ms->possible_cpus->len; i++) {
574         CpuInstanceProperties *props = &ms->possible_cpus->cpus[i].props;
575 
576         ms->possible_cpus->cpus[i].type = ms->cpu_type;
577         ms->possible_cpus->cpus[i].vcpus_count = 1;
578         ms->possible_cpus->cpus[i].arch_id = i;
579 
580         props->has_core_id = true;
581         props->core_id = i;
582         props->has_socket_id = true;
583         props->socket_id = s390_std_socket(i, &ms->smp);
584         props->has_book_id = true;
585         props->book_id = s390_std_book(i, &ms->smp);
586         props->has_drawer_id = true;
587         props->drawer_id = s390_std_drawer(i, &ms->smp);
588     }
589 
590     return ms->possible_cpus;
591 }
592 
593 static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
594                                                 DeviceState *dev)
595 {
596     if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
597         return HOTPLUG_HANDLER(machine);
598     }
599     return NULL;
600 }
601 
602 static void s390_nmi(NMIState *n, int cpu_index, Error **errp)
603 {
604     CPUState *cs = qemu_get_cpu(cpu_index);
605 
606     s390_cpu_restart(S390_CPU(cs));
607 }
608 
609 static ram_addr_t s390_fixup_ram_size(ram_addr_t sz)
610 {
611     /* same logic as in sclp.c */
612     int increment_size = 20;
613     ram_addr_t newsz;
614 
615     while ((sz >> increment_size) > MAX_STORAGE_INCREMENTS) {
616         increment_size++;
617     }
618     newsz = sz >> increment_size << increment_size;
619 
620     if (sz != newsz) {
621         qemu_printf("Ram size %" PRIu64 "MB was fixed up to %" PRIu64
622                     "MB to match machine restrictions. Consider updating "
623                     "the guest definition.\n", (uint64_t) (sz / MiB),
624                     (uint64_t) (newsz / MiB));
625     }
626     return newsz;
627 }
628 
629 static inline bool machine_get_aes_key_wrap(Object *obj, Error **errp)
630 {
631     S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
632 
633     return ms->aes_key_wrap;
634 }
635 
636 static inline void machine_set_aes_key_wrap(Object *obj, bool value,
637                                             Error **errp)
638 {
639     S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
640 
641     ms->aes_key_wrap = value;
642 }
643 
644 static inline bool machine_get_dea_key_wrap(Object *obj, Error **errp)
645 {
646     S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
647 
648     return ms->dea_key_wrap;
649 }
650 
651 static inline void machine_set_dea_key_wrap(Object *obj, bool value,
652                                             Error **errp)
653 {
654     S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
655 
656     ms->dea_key_wrap = value;
657 }
658 
659 static S390CcwMachineClass *current_mc;
660 
661 /*
662  * Get the class of the s390-ccw-virtio machine that is currently in use.
663  * Note: libvirt is using the "none" machine to probe for the features of the
664  * host CPU, so in case this is called with the "none" machine, the function
665  * returns the TYPE_S390_CCW_MACHINE base class. In this base class, all the
666  * various "*_allowed" variables are enabled, so that the *_allowed() wrappers
667  * below return the correct default value for the "none" machine.
668  *
669  * Attention! Do *not* add additional new wrappers for CPU features (e.g. like
670  * the ri_allowed() wrapper) via this mechanism anymore. CPU features should
671  * be handled via the CPU models, i.e. checking with cpu_model_allowed() during
672  * CPU initialization and s390_has_feat() later should be sufficient.
673  */
674 static S390CcwMachineClass *get_machine_class(void)
675 {
676     if (unlikely(!current_mc)) {
677         /*
678         * No s390 ccw machine was instantiated, we are likely to
679         * be called for the 'none' machine. The properties will
680         * have their after-initialization values.
681         */
682         current_mc = S390_CCW_MACHINE_CLASS(
683                      object_class_by_name(TYPE_S390_CCW_MACHINE));
684     }
685     return current_mc;
686 }
687 
688 bool ri_allowed(void)
689 {
690     return get_machine_class()->ri_allowed;
691 }
692 
693 bool cpu_model_allowed(void)
694 {
695     return get_machine_class()->cpu_model_allowed;
696 }
697 
698 bool hpage_1m_allowed(void)
699 {
700     return get_machine_class()->hpage_1m_allowed;
701 }
702 
703 static void machine_get_loadparm(Object *obj, Visitor *v,
704                                  const char *name, void *opaque,
705                                  Error **errp)
706 {
707     S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
708     char *str = g_strndup((char *) ms->loadparm, sizeof(ms->loadparm));
709 
710     visit_type_str(v, name, &str, errp);
711     g_free(str);
712 }
713 
714 static void machine_set_loadparm(Object *obj, Visitor *v,
715                                  const char *name, void *opaque,
716                                  Error **errp)
717 {
718     S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
719     char *val;
720     int i;
721 
722     if (!visit_type_str(v, name, &val, errp)) {
723         return;
724     }
725 
726     for (i = 0; i < sizeof(ms->loadparm) && val[i]; i++) {
727         uint8_t c = qemu_toupper(val[i]); /* mimic HMC */
728 
729         if (('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || (c == '.') ||
730             (c == ' ')) {
731             ms->loadparm[i] = c;
732         } else {
733             error_setg(errp, "LOADPARM: invalid character '%c' (ASCII 0x%02x)",
734                        c, c);
735             return;
736         }
737     }
738 
739     for (; i < sizeof(ms->loadparm); i++) {
740         ms->loadparm[i] = ' '; /* pad right with spaces */
741     }
742 }
743 
744 static void ccw_machine_class_init(ObjectClass *oc, void *data)
745 {
746     MachineClass *mc = MACHINE_CLASS(oc);
747     NMIClass *nc = NMI_CLASS(oc);
748     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
749     S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
750 
751     s390mc->ri_allowed = true;
752     s390mc->cpu_model_allowed = true;
753     s390mc->css_migration_enabled = true;
754     s390mc->hpage_1m_allowed = true;
755     s390mc->max_threads = 1;
756     mc->init = ccw_init;
757     mc->reset = s390_machine_reset;
758     mc->block_default_type = IF_VIRTIO;
759     mc->no_cdrom = 1;
760     mc->no_floppy = 1;
761     mc->no_parallel = 1;
762     mc->no_sdcard = 1;
763     mc->max_cpus = S390_MAX_CPUS;
764     mc->has_hotpluggable_cpus = true;
765     mc->smp_props.books_supported = true;
766     mc->smp_props.drawers_supported = true;
767     assert(!mc->get_hotplug_handler);
768     mc->get_hotplug_handler = s390_get_hotplug_handler;
769     mc->cpu_index_to_instance_props = s390_cpu_index_to_props;
770     mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids;
771     /* it is overridden with 'host' cpu *in kvm_arch_init* */
772     mc->default_cpu_type = S390_CPU_TYPE_NAME("qemu");
773     hc->plug = s390_machine_device_plug;
774     hc->unplug_request = s390_machine_device_unplug_request;
775     nc->nmi_monitor_handler = s390_nmi;
776     mc->default_ram_id = "s390.ram";
777     mc->default_nic = "virtio-net-ccw";
778 
779     object_class_property_add_bool(oc, "aes-key-wrap",
780                                    machine_get_aes_key_wrap,
781                                    machine_set_aes_key_wrap);
782     object_class_property_set_description(oc, "aes-key-wrap",
783             "enable/disable AES key wrapping using the CPACF wrapping key");
784 
785     object_class_property_add_bool(oc, "dea-key-wrap",
786                                    machine_get_dea_key_wrap,
787                                    machine_set_dea_key_wrap);
788     object_class_property_set_description(oc, "dea-key-wrap",
789             "enable/disable DEA key wrapping using the CPACF wrapping key");
790 
791     object_class_property_add(oc, "loadparm", "loadparm",
792                               machine_get_loadparm, machine_set_loadparm,
793                               NULL, NULL);
794     object_class_property_set_description(oc, "loadparm",
795             "Up to 8 chars in set of [A-Za-z0-9. ] (lower case chars converted"
796             " to upper case) to pass to machine loader, boot manager,"
797             " and guest kernel");
798 }
799 
800 static inline void s390_machine_initfn(Object *obj)
801 {
802     S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
803 
804     ms->aes_key_wrap = true;
805     ms->dea_key_wrap = true;
806 }
807 
808 static const TypeInfo ccw_machine_info = {
809     .name          = TYPE_S390_CCW_MACHINE,
810     .parent        = TYPE_MACHINE,
811     .abstract      = true,
812     .instance_size = sizeof(S390CcwMachineState),
813     .instance_init = s390_machine_initfn,
814     .class_size = sizeof(S390CcwMachineClass),
815     .class_init    = ccw_machine_class_init,
816     .interfaces = (InterfaceInfo[]) {
817         { TYPE_NMI },
818         { TYPE_HOTPLUG_HANDLER},
819         { }
820     },
821 };
822 
823 bool css_migration_enabled(void)
824 {
825     return get_machine_class()->css_migration_enabled;
826 }
827 
828 #define DEFINE_CCW_MACHINE(suffix, verstr, latest)                            \
829     static void ccw_machine_##suffix##_class_init(ObjectClass *oc,            \
830                                                   void *data)                 \
831     {                                                                         \
832         MachineClass *mc = MACHINE_CLASS(oc);                                 \
833         ccw_machine_##suffix##_class_options(mc);                             \
834         mc->desc = "Virtual s390x machine (version " verstr ")";              \
835         if (latest) {                                                         \
836             mc->alias = "s390-ccw-virtio";                                    \
837             mc->is_default = true;                                            \
838         }                                                                     \
839     }                                                                         \
840     static void ccw_machine_##suffix##_instance_init(Object *obj)             \
841     {                                                                         \
842         MachineState *machine = MACHINE(obj);                                 \
843         current_mc = S390_CCW_MACHINE_CLASS(MACHINE_GET_CLASS(machine));          \
844         ccw_machine_##suffix##_instance_options(machine);                     \
845     }                                                                         \
846     static const TypeInfo ccw_machine_##suffix##_info = {                     \
847         .name = MACHINE_TYPE_NAME("s390-ccw-virtio-" verstr),                 \
848         .parent = TYPE_S390_CCW_MACHINE,                                      \
849         .class_init = ccw_machine_##suffix##_class_init,                      \
850         .instance_init = ccw_machine_##suffix##_instance_init,                \
851     };                                                                        \
852     static void ccw_machine_register_##suffix(void)                           \
853     {                                                                         \
854         type_register_static(&ccw_machine_##suffix##_info);                   \
855     }                                                                         \
856     type_init(ccw_machine_register_##suffix)
857 
858 static void ccw_machine_8_2_instance_options(MachineState *machine)
859 {
860 }
861 
862 static void ccw_machine_8_2_class_options(MachineClass *mc)
863 {
864 }
865 DEFINE_CCW_MACHINE(8_2, "8.2", true);
866 
867 static void ccw_machine_8_1_instance_options(MachineState *machine)
868 {
869     ccw_machine_8_2_instance_options(machine);
870 }
871 
872 static void ccw_machine_8_1_class_options(MachineClass *mc)
873 {
874     ccw_machine_8_2_class_options(mc);
875     compat_props_add(mc->compat_props, hw_compat_8_1, hw_compat_8_1_len);
876     mc->smp_props.drawers_supported = false;
877     mc->smp_props.books_supported = false;
878 }
879 DEFINE_CCW_MACHINE(8_1, "8.1", false);
880 
881 static void ccw_machine_8_0_instance_options(MachineState *machine)
882 {
883     ccw_machine_8_1_instance_options(machine);
884 }
885 
886 static void ccw_machine_8_0_class_options(MachineClass *mc)
887 {
888     ccw_machine_8_1_class_options(mc);
889     compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len);
890 }
891 DEFINE_CCW_MACHINE(8_0, "8.0", false);
892 
893 static void ccw_machine_7_2_instance_options(MachineState *machine)
894 {
895     ccw_machine_8_0_instance_options(machine);
896 }
897 
898 static void ccw_machine_7_2_class_options(MachineClass *mc)
899 {
900     ccw_machine_8_0_class_options(mc);
901     compat_props_add(mc->compat_props, hw_compat_7_2, hw_compat_7_2_len);
902 }
903 DEFINE_CCW_MACHINE(7_2, "7.2", false);
904 
905 static void ccw_machine_7_1_instance_options(MachineState *machine)
906 {
907     static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V7_1 };
908 
909     ccw_machine_7_2_instance_options(machine);
910     s390_cpudef_featoff_greater(16, 1, S390_FEAT_PAIE);
911     s390_set_qemu_cpu_model(0x8561, 15, 1, qemu_cpu_feat);
912 }
913 
914 static void ccw_machine_7_1_class_options(MachineClass *mc)
915 {
916     S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
917     static GlobalProperty compat[] = {
918         { TYPE_S390_PCI_DEVICE, "interpret", "off", },
919         { TYPE_S390_PCI_DEVICE, "forwarding-assist", "off", },
920     };
921 
922     ccw_machine_7_2_class_options(mc);
923     compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len);
924     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
925     s390mc->max_threads = S390_MAX_CPUS;
926 }
927 DEFINE_CCW_MACHINE(7_1, "7.1", false);
928 
929 static void ccw_machine_7_0_instance_options(MachineState *machine)
930 {
931     static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V7_0 };
932 
933     ccw_machine_7_1_instance_options(machine);
934     s390_set_qemu_cpu_model(0x8561, 15, 1, qemu_cpu_feat);
935 }
936 
937 static void ccw_machine_7_0_class_options(MachineClass *mc)
938 {
939     ccw_machine_7_1_class_options(mc);
940     compat_props_add(mc->compat_props, hw_compat_7_0, hw_compat_7_0_len);
941 }
942 DEFINE_CCW_MACHINE(7_0, "7.0", false);
943 
944 static void ccw_machine_6_2_instance_options(MachineState *machine)
945 {
946     static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V6_2 };
947 
948     ccw_machine_7_0_instance_options(machine);
949     s390_set_qemu_cpu_model(0x3906, 14, 2, qemu_cpu_feat);
950 }
951 
952 static void ccw_machine_6_2_class_options(MachineClass *mc)
953 {
954     ccw_machine_7_0_class_options(mc);
955     compat_props_add(mc->compat_props, hw_compat_6_2, hw_compat_6_2_len);
956 }
957 DEFINE_CCW_MACHINE(6_2, "6.2", false);
958 
959 static void ccw_machine_6_1_instance_options(MachineState *machine)
960 {
961     ccw_machine_6_2_instance_options(machine);
962     s390_cpudef_featoff_greater(16, 1, S390_FEAT_NNPA);
963     s390_cpudef_featoff_greater(16, 1, S390_FEAT_VECTOR_PACKED_DECIMAL_ENH2);
964     s390_cpudef_featoff_greater(16, 1, S390_FEAT_BEAR_ENH);
965     s390_cpudef_featoff_greater(16, 1, S390_FEAT_RDP);
966     s390_cpudef_featoff_greater(16, 1, S390_FEAT_PAI);
967 }
968 
969 static void ccw_machine_6_1_class_options(MachineClass *mc)
970 {
971     ccw_machine_6_2_class_options(mc);
972     compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
973     mc->smp_props.prefer_sockets = true;
974 }
975 DEFINE_CCW_MACHINE(6_1, "6.1", false);
976 
977 static void ccw_machine_6_0_instance_options(MachineState *machine)
978 {
979     static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V6_0 };
980 
981     ccw_machine_6_1_instance_options(machine);
982     s390_set_qemu_cpu_model(0x2964, 13, 2, qemu_cpu_feat);
983 }
984 
985 static void ccw_machine_6_0_class_options(MachineClass *mc)
986 {
987     ccw_machine_6_1_class_options(mc);
988     compat_props_add(mc->compat_props, hw_compat_6_0, hw_compat_6_0_len);
989 }
990 DEFINE_CCW_MACHINE(6_0, "6.0", false);
991 
992 static void ccw_machine_5_2_instance_options(MachineState *machine)
993 {
994     ccw_machine_6_0_instance_options(machine);
995 }
996 
997 static void ccw_machine_5_2_class_options(MachineClass *mc)
998 {
999     ccw_machine_6_0_class_options(mc);
1000     compat_props_add(mc->compat_props, hw_compat_5_2, hw_compat_5_2_len);
1001 }
1002 DEFINE_CCW_MACHINE(5_2, "5.2", false);
1003 
1004 static void ccw_machine_5_1_instance_options(MachineState *machine)
1005 {
1006     ccw_machine_5_2_instance_options(machine);
1007 }
1008 
1009 static void ccw_machine_5_1_class_options(MachineClass *mc)
1010 {
1011     ccw_machine_5_2_class_options(mc);
1012     compat_props_add(mc->compat_props, hw_compat_5_1, hw_compat_5_1_len);
1013 }
1014 DEFINE_CCW_MACHINE(5_1, "5.1", false);
1015 
1016 static void ccw_machine_5_0_instance_options(MachineState *machine)
1017 {
1018     ccw_machine_5_1_instance_options(machine);
1019 }
1020 
1021 static void ccw_machine_5_0_class_options(MachineClass *mc)
1022 {
1023     ccw_machine_5_1_class_options(mc);
1024     compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len);
1025 }
1026 DEFINE_CCW_MACHINE(5_0, "5.0", false);
1027 
1028 static void ccw_machine_4_2_instance_options(MachineState *machine)
1029 {
1030     ccw_machine_5_0_instance_options(machine);
1031 }
1032 
1033 static void ccw_machine_4_2_class_options(MachineClass *mc)
1034 {
1035     ccw_machine_5_0_class_options(mc);
1036     mc->fixup_ram_size = s390_fixup_ram_size;
1037     compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
1038 }
1039 DEFINE_CCW_MACHINE(4_2, "4.2", false);
1040 
1041 static void ccw_machine_4_1_instance_options(MachineState *machine)
1042 {
1043     static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V4_1 };
1044     ccw_machine_4_2_instance_options(machine);
1045     s390_set_qemu_cpu_model(0x2964, 13, 2, qemu_cpu_feat);
1046 }
1047 
1048 static void ccw_machine_4_1_class_options(MachineClass *mc)
1049 {
1050     ccw_machine_4_2_class_options(mc);
1051     compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len);
1052 }
1053 DEFINE_CCW_MACHINE(4_1, "4.1", false);
1054 
1055 static void ccw_machine_4_0_instance_options(MachineState *machine)
1056 {
1057     static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V4_0 };
1058     ccw_machine_4_1_instance_options(machine);
1059     s390_set_qemu_cpu_model(0x2827, 12, 2, qemu_cpu_feat);
1060 }
1061 
1062 static void ccw_machine_4_0_class_options(MachineClass *mc)
1063 {
1064     ccw_machine_4_1_class_options(mc);
1065     compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
1066 }
1067 DEFINE_CCW_MACHINE(4_0, "4.0", false);
1068 
1069 static void ccw_machine_3_1_instance_options(MachineState *machine)
1070 {
1071     static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V3_1 };
1072     ccw_machine_4_0_instance_options(machine);
1073     s390_cpudef_featoff_greater(14, 1, S390_FEAT_MULTIPLE_EPOCH);
1074     s390_cpudef_group_featoff_greater(14, 1, S390_FEAT_GROUP_MULTIPLE_EPOCH_PTFF);
1075     s390_set_qemu_cpu_model(0x2827, 12, 2, qemu_cpu_feat);
1076 }
1077 
1078 static void ccw_machine_3_1_class_options(MachineClass *mc)
1079 {
1080     ccw_machine_4_0_class_options(mc);
1081     compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len);
1082 }
1083 DEFINE_CCW_MACHINE(3_1, "3.1", false);
1084 
1085 static void ccw_machine_3_0_instance_options(MachineState *machine)
1086 {
1087     ccw_machine_3_1_instance_options(machine);
1088 }
1089 
1090 static void ccw_machine_3_0_class_options(MachineClass *mc)
1091 {
1092     S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
1093 
1094     s390mc->hpage_1m_allowed = false;
1095     ccw_machine_3_1_class_options(mc);
1096     compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len);
1097 }
1098 DEFINE_CCW_MACHINE(3_0, "3.0", false);
1099 
1100 static void ccw_machine_2_12_instance_options(MachineState *machine)
1101 {
1102     ccw_machine_3_0_instance_options(machine);
1103     s390_cpudef_featoff_greater(11, 1, S390_FEAT_PPA15);
1104     s390_cpudef_featoff_greater(11, 1, S390_FEAT_BPB);
1105 }
1106 
1107 static void ccw_machine_2_12_class_options(MachineClass *mc)
1108 {
1109     ccw_machine_3_0_class_options(mc);
1110     compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len);
1111 }
1112 DEFINE_CCW_MACHINE(2_12, "2.12", false);
1113 
1114 static void ccw_machine_2_11_instance_options(MachineState *machine)
1115 {
1116     static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V2_11 };
1117     ccw_machine_2_12_instance_options(machine);
1118 
1119     /* before 2.12 we emulated the very first z900 */
1120     s390_set_qemu_cpu_model(0x2064, 7, 1, qemu_cpu_feat);
1121 }
1122 
1123 static void ccw_machine_2_11_class_options(MachineClass *mc)
1124 {
1125     static GlobalProperty compat[] = {
1126         { TYPE_SCLP_EVENT_FACILITY, "allow_all_mask_sizes", "off", },
1127     };
1128 
1129     ccw_machine_2_12_class_options(mc);
1130     compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len);
1131     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
1132 }
1133 DEFINE_CCW_MACHINE(2_11, "2.11", false);
1134 
1135 static void ccw_machine_2_10_instance_options(MachineState *machine)
1136 {
1137     ccw_machine_2_11_instance_options(machine);
1138 }
1139 
1140 static void ccw_machine_2_10_class_options(MachineClass *mc)
1141 {
1142     ccw_machine_2_11_class_options(mc);
1143     compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len);
1144 }
1145 DEFINE_CCW_MACHINE(2_10, "2.10", false);
1146 
1147 static void ccw_machine_2_9_instance_options(MachineState *machine)
1148 {
1149     ccw_machine_2_10_instance_options(machine);
1150     s390_cpudef_featoff_greater(12, 1, S390_FEAT_ESOP);
1151     s390_cpudef_featoff_greater(12, 1, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2);
1152     s390_cpudef_featoff_greater(12, 1, S390_FEAT_ZPCI);
1153     s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_INT_SUPPRESSION);
1154     s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_EVENT_NOTIFICATION);
1155 }
1156 
1157 static void ccw_machine_2_9_class_options(MachineClass *mc)
1158 {
1159     S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
1160     static GlobalProperty compat[] = {
1161         { TYPE_S390_STATTRIB, "migration-enabled", "off", },
1162     };
1163 
1164     ccw_machine_2_10_class_options(mc);
1165     compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len);
1166     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
1167     s390mc->css_migration_enabled = false;
1168 }
1169 DEFINE_CCW_MACHINE(2_9, "2.9", false);
1170 
1171 static void ccw_machine_2_8_instance_options(MachineState *machine)
1172 {
1173     ccw_machine_2_9_instance_options(machine);
1174 }
1175 
1176 static void ccw_machine_2_8_class_options(MachineClass *mc)
1177 {
1178     static GlobalProperty compat[] = {
1179         { TYPE_S390_FLIC_COMMON, "adapter_routes_max_batch", "64", },
1180     };
1181 
1182     ccw_machine_2_9_class_options(mc);
1183     compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len);
1184     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
1185 }
1186 DEFINE_CCW_MACHINE(2_8, "2.8", false);
1187 
1188 static void ccw_machine_2_7_instance_options(MachineState *machine)
1189 {
1190     ccw_machine_2_8_instance_options(machine);
1191 }
1192 
1193 static void ccw_machine_2_7_class_options(MachineClass *mc)
1194 {
1195     S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
1196 
1197     s390mc->cpu_model_allowed = false;
1198     ccw_machine_2_8_class_options(mc);
1199     compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len);
1200 }
1201 DEFINE_CCW_MACHINE(2_7, "2.7", false);
1202 
1203 static void ccw_machine_2_6_instance_options(MachineState *machine)
1204 {
1205     ccw_machine_2_7_instance_options(machine);
1206 }
1207 
1208 static void ccw_machine_2_6_class_options(MachineClass *mc)
1209 {
1210     S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
1211     static GlobalProperty compat[] = {
1212         { TYPE_S390_IPL, "iplbext_migration", "off", },
1213          { TYPE_VIRTUAL_CSS_BRIDGE, "css_dev_path", "off", },
1214     };
1215 
1216     s390mc->ri_allowed = false;
1217     ccw_machine_2_7_class_options(mc);
1218     compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len);
1219     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
1220 }
1221 DEFINE_CCW_MACHINE(2_6, "2.6", false);
1222 
1223 static void ccw_machine_2_5_instance_options(MachineState *machine)
1224 {
1225     ccw_machine_2_6_instance_options(machine);
1226 }
1227 
1228 static void ccw_machine_2_5_class_options(MachineClass *mc)
1229 {
1230     ccw_machine_2_6_class_options(mc);
1231     compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len);
1232 }
1233 DEFINE_CCW_MACHINE(2_5, "2.5", false);
1234 
1235 static void ccw_machine_2_4_instance_options(MachineState *machine)
1236 {
1237     ccw_machine_2_5_instance_options(machine);
1238 }
1239 
1240 static void ccw_machine_2_4_class_options(MachineClass *mc)
1241 {
1242     static GlobalProperty compat[] = {
1243         { TYPE_S390_SKEYS, "migration-enabled", "off", },
1244         { "virtio-blk-ccw", "max_revision", "0", },
1245         { "virtio-balloon-ccw", "max_revision", "0", },
1246         { "virtio-serial-ccw", "max_revision", "0", },
1247         { "virtio-9p-ccw", "max_revision", "0", },
1248         { "virtio-rng-ccw", "max_revision", "0", },
1249         { "virtio-net-ccw", "max_revision", "0", },
1250         { "virtio-scsi-ccw", "max_revision", "0", },
1251         { "vhost-scsi-ccw", "max_revision", "0", },
1252     };
1253 
1254     ccw_machine_2_5_class_options(mc);
1255     compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len);
1256     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
1257 }
1258 DEFINE_CCW_MACHINE(2_4, "2.4", false);
1259 
1260 static void ccw_machine_register_types(void)
1261 {
1262     type_register_static(&ccw_machine_info);
1263 }
1264 
1265 type_init(ccw_machine_register_types)
1266