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