]> git.proxmox.com Git - mirror_qemu.git/blame - hw/s390x/s390-virtio-ccw.c
s390x: implement query-hotpluggable-cpus
[mirror_qemu.git] / hw / s390x / s390-virtio-ccw.c
CommitLineData
a5c95808
CH
1/*
2 * virtio ccw machine
3 *
4 * Copyright 2012 IBM Corp.
6286b419 5 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
a5c95808
CH
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
9615495a 13#include "qemu/osdep.h"
da34e65c 14#include "qapi/error.h"
4771d756
PB
15#include "qemu-common.h"
16#include "cpu.h"
a5c95808
CH
17#include "hw/boards.h"
18#include "exec/address-spaces.h"
7d577546 19#include "hw/s390x/s390-virtio-hcall.h"
83c9f4ca 20#include "hw/s390x/sclp.h"
3a553fc6 21#include "hw/s390x/s390_flic.h"
bd3f16ac
PB
22#include "hw/s390x/ioinst.h"
23#include "hw/s390x/css.h"
a5c95808 24#include "virtio-ccw.h"
b6fe0124 25#include "qemu/config-file.h"
b5684cd8 26#include "qemu/error-report.h"
8cba80c3 27#include "s390-pci-bus.h"
0f5f6691 28#include "hw/s390x/storage-keys.h"
903fd80b 29#include "hw/s390x/storage-attributes.h"
54d8ec84 30#include "hw/compat.h"
04ca4b92 31#include "ipl.h"
8b8a61ad 32#include "hw/s390x/s390-virtio-ccw.h"
dd70bd0d 33#include "hw/s390x/css-bridge.h"
f2a8f0a6 34#include "migration/register.h"
7223bcce 35#include "cpu_models.h"
6286b419
DH
36#include "qapi/qmp/qerror.h"
37#include "hw/nmi.h"
38
39static S390CPU **cpu_states;
40
41S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
42{
43 if (cpu_addr >= max_cpus) {
44 return NULL;
45 }
46
47 /* Fast lookup via CPU ID */
48 return cpu_states[cpu_addr];
49}
50
51static void s390_init_cpus(MachineState *machine)
52{
4dc3b151 53 MachineClass *mc = MACHINE_GET_CLASS(machine);
6286b419
DH
54 int i;
55 gchar *name;
56
57 if (machine->cpu_model == NULL) {
58 machine->cpu_model = s390_default_cpu_model_name();
59 }
b5684cd8
DH
60 if (tcg_enabled() && max_cpus > 1) {
61 error_report("Number of SMP CPUs requested (%d) exceeds max CPUs "
62 "supported by TCG (1) on s390x", max_cpus);
63 exit(1);
64 }
6286b419
DH
65
66 cpu_states = g_new0(S390CPU *, max_cpus);
67
68 for (i = 0; i < max_cpus; i++) {
69 name = g_strdup_printf("cpu[%i]", i);
70 object_property_add_link(OBJECT(machine), name, TYPE_S390_CPU,
71 (Object **) &cpu_states[i],
72 object_property_allow_set_link,
73 OBJ_PROP_LINK_UNREF_ON_RELEASE,
74 &error_abort);
75 g_free(name);
76 }
77
4dc3b151
DH
78 /* initialize possible_cpus */
79 mc->possible_cpu_arch_ids(machine);
80
6286b419
DH
81 for (i = 0; i < smp_cpus; i++) {
82 s390x_new_cpu(machine->cpu_model, i, &error_fatal);
83 }
84}
2eb1cd07 85
09c7f58c 86static const char *const reset_dev_types[] = {
3f9e4859 87 TYPE_VIRTUAL_CSS_BRIDGE,
09c7f58c
DH
88 "s390-sclp-event-facility",
89 "s390-flic",
90 "diag288",
91};
92
d9f090ec 93void subsystem_reset(void)
4e872a3f 94{
09c7f58c
DH
95 DeviceState *dev;
96 int i;
4e872a3f 97
09c7f58c
DH
98 for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) {
99 dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL));
100 if (dev) {
101 qdev_reset_all(dev);
102 }
0c7322cf 103 }
4e872a3f
CB
104}
105
a5c95808
CH
106static int virtio_ccw_hcall_notify(const uint64_t *args)
107{
108 uint64_t subch_id = args[0];
109 uint64_t queue = args[1];
110 SubchDev *sch;
111 int cssid, ssid, schid, m;
112
113 if (ioinst_disassemble_sch_ident(subch_id, &m, &cssid, &ssid, &schid)) {
114 return -EINVAL;
115 }
116 sch = css_find_subch(m, cssid, ssid, schid);
117 if (!sch || !css_subch_visible(sch)) {
118 return -EINVAL;
119 }
b1914b82 120 if (queue >= VIRTIO_QUEUE_MAX) {
b57ed9bf
CH
121 return -EINVAL;
122 }
a5c95808
CH
123 virtio_queue_notify(virtio_ccw_get_vdev(sch), queue);
124 return 0;
125
126}
127
128static int virtio_ccw_hcall_early_printk(const uint64_t *args)
129{
130 uint64_t mem = args[0];
131
132 if (mem < ram_size) {
133 /* Early printk */
134 return 0;
135 }
136 return -EINVAL;
137}
138
139static void virtio_ccw_register_hcalls(void)
140{
141 s390_register_virtio_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY,
142 virtio_ccw_hcall_notify);
143 /* Tolerate early printk. */
144 s390_register_virtio_hypercall(KVM_S390_VIRTIO_NOTIFY,
145 virtio_ccw_hcall_early_printk);
146}
147
6286b419 148static void s390_memory_init(ram_addr_t mem_size)
a5c95808 149{
a5c95808
CH
150 MemoryRegion *sysmem = get_system_memory();
151 MemoryRegion *ram = g_new(MemoryRegion, 1);
80d23275
DH
152
153 /* allocate RAM for core */
ae23a335 154 memory_region_allocate_system_memory(ram, NULL, "s390.ram", mem_size);
80d23275
DH
155 memory_region_add_subregion(sysmem, 0, ram);
156
157 /* Initialize storage key device */
158 s390_skeys_init();
903fd80b
CI
159 /* Initialize storage attributes device */
160 s390_stattrib_init();
80d23275
DH
161}
162
6286b419
DH
163#define S390_TOD_CLOCK_VALUE_MISSING 0x00
164#define S390_TOD_CLOCK_VALUE_PRESENT 0x01
165
166static void gtod_save(QEMUFile *f, void *opaque)
167{
168 uint64_t tod_low;
169 uint8_t tod_high;
170 int r;
171
172 r = s390_get_clock(&tod_high, &tod_low);
173 if (r) {
174 warn_report("Unable to get guest clock for migration: %s",
175 strerror(-r));
176 error_printf("Guest clock will not be migrated "
177 "which could cause the guest to hang.");
178 qemu_put_byte(f, S390_TOD_CLOCK_VALUE_MISSING);
179 return;
180 }
181
182 qemu_put_byte(f, S390_TOD_CLOCK_VALUE_PRESENT);
183 qemu_put_byte(f, tod_high);
184 qemu_put_be64(f, tod_low);
185}
186
187static int gtod_load(QEMUFile *f, void *opaque, int version_id)
188{
189 uint64_t tod_low;
190 uint8_t tod_high;
191 int r;
192
193 if (qemu_get_byte(f) == S390_TOD_CLOCK_VALUE_MISSING) {
194 warn_report("Guest clock was not migrated. This could "
195 "cause the guest to hang.");
196 return 0;
197 }
198
199 tod_high = qemu_get_byte(f);
200 tod_low = qemu_get_be64(f);
201
202 r = s390_set_clock(&tod_high, &tod_low);
203 if (r) {
204 warn_report("Unable to set guest clock for migration: %s",
205 strerror(-r));
206 error_printf("Guest clock will not be restored "
207 "which could cause the guest to hang.");
208 }
209
210 return 0;
211}
212
1b6e7482
LV
213static SaveVMHandlers savevm_gtod = {
214 .save_state = gtod_save,
215 .load_state = gtod_load,
216};
217
6286b419
DH
218static void s390_init_ipl_dev(const char *kernel_filename,
219 const char *kernel_cmdline,
220 const char *initrd_filename, const char *firmware,
221 const char *netboot_fw, bool enforce_bios)
222{
223 Object *new = object_new(TYPE_S390_IPL);
224 DeviceState *dev = DEVICE(new);
225
226 if (kernel_filename) {
227 qdev_prop_set_string(dev, "kernel", kernel_filename);
228 }
229 if (initrd_filename) {
230 qdev_prop_set_string(dev, "initrd", initrd_filename);
231 }
232 qdev_prop_set_string(dev, "cmdline", kernel_cmdline);
233 qdev_prop_set_string(dev, "firmware", firmware);
234 qdev_prop_set_string(dev, "netboot_fw", netboot_fw);
235 qdev_prop_set_bit(dev, "enforce_bios", enforce_bios);
236 object_property_add_child(qdev_get_machine(), TYPE_S390_IPL,
237 new, NULL);
238 object_unref(new);
239 qdev_init_nofail(dev);
240}
241
242static void s390_create_virtio_net(BusState *bus, const char *name)
243{
244 int i;
245
246 for (i = 0; i < nb_nics; i++) {
247 NICInfo *nd = &nd_table[i];
248 DeviceState *dev;
249
250 if (!nd->model) {
251 nd->model = g_strdup("virtio");
252 }
253
254 qemu_check_nic_model(nd, "virtio");
255
256 dev = qdev_create(bus, name);
257 qdev_set_nic_properties(dev, nd);
258 qdev_init_nofail(dev);
259 }
260}
261
80d23275
DH
262static void ccw_init(MachineState *machine)
263{
a5c95808
CH
264 int ret;
265 VirtualCssBus *css_bus;
b6fe0124 266
1cf065fb 267 s390_sclp_init();
80d23275 268 s390_memory_init(machine->ram_size);
a5c95808 269
d32bd032 270 /* init CPUs (incl. CPU model) early so s390_has_feature() works */
3720d335
YMZ
271 s390_init_cpus(machine);
272
c572d3f3
FL
273 s390_flic_init();
274
a5c95808
CH
275 /* get a BUS */
276 css_bus = virtual_css_bus_init();
3ef96221 277 s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline,
5f31ade0
FA
278 machine->initrd_filename, "s390-ccw.img",
279 "s390-netboot.img", true);
a5c95808 280
d32bd032
CH
281 if (s390_has_feat(S390_FEAT_ZPCI)) {
282 DeviceState *dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE);
283 object_property_add_child(qdev_get_machine(),
284 TYPE_S390_PCI_HOST_BRIDGE,
285 OBJECT(dev), NULL);
286 qdev_init_nofail(dev);
287 }
8cba80c3 288
a5c95808
CH
289 /* register hypercalls */
290 virtio_ccw_register_hcalls();
291
5e7164c5 292 s390_enable_css_support(s390_cpu_addr2state(0));
a5c95808 293 /*
817d4a6b
DJS
294 * Non mcss-e enabled guests only see the devices from the default
295 * css, which is determined by the value of the squash_mcss property.
296 * Note: we must not squash non virtual devices to css 0xFE.
a5c95808 297 */
817d4a6b
DJS
298 if (css_bus->squash_mcss) {
299 ret = css_create_css_image(0, true);
300 } else {
301 ret = css_create_css_image(VIRTUAL_CSSID, true);
302 }
a5c95808
CH
303 assert(ret == 0);
304
305 /* Create VirtIO network adapters */
306 s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw");
3f9e59bb
JH
307
308 /* Register savevm handler for guest TOD clock */
fe7cb8ea 309 register_savevm_live(NULL, "todclock", 0, 1, &savevm_gtod, NULL);
a5c95808
CH
310}
311
502edbf8
MR
312static void s390_cpu_plug(HotplugHandler *hotplug_dev,
313 DeviceState *dev, Error **errp)
314{
315 gchar *name;
4dc3b151 316 MachineState *ms = MACHINE(hotplug_dev);
502edbf8
MR
317 S390CPU *cpu = S390_CPU(dev);
318 CPUState *cs = CPU(dev);
319
ca5c1457 320 name = g_strdup_printf("cpu[%i]", cpu->env.core_id);
502edbf8
MR
321 object_property_set_link(OBJECT(hotplug_dev), OBJECT(cs), name,
322 errp);
323 g_free(name);
4dc3b151
DH
324
325 g_assert(!ms->possible_cpus->cpus[cpu->env.core_id].cpu);
326 ms->possible_cpus->cpus[cpu->env.core_id].cpu = OBJECT(dev);
502edbf8
MR
327}
328
6286b419
DH
329static void s390_machine_reset(void)
330{
331 S390CPU *ipl_cpu = S390_CPU(qemu_get_cpu(0));
332
333 s390_cmma_reset();
334 qemu_devices_reset();
335 s390_crypto_reset();
336
337 /* all cpus are stopped - configure and start the ipl cpu only */
338 s390_ipl_prepare_cpu(ipl_cpu);
339 s390_cpu_set_state(CPU_STATE_OPERATING, ipl_cpu);
340}
341
502edbf8
MR
342static void s390_machine_device_plug(HotplugHandler *hotplug_dev,
343 DeviceState *dev, Error **errp)
344{
345 if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
346 s390_cpu_plug(hotplug_dev, dev, errp);
347 }
348}
349
f2f3beb0
DH
350static void s390_machine_device_unplug_request(HotplugHandler *hotplug_dev,
351 DeviceState *dev, Error **errp)
352{
353 if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
354 error_setg(errp, "CPU hot unplug not supported on this machine");
355 return;
356 }
357}
358
4dc3b151
DH
359static CpuInstanceProperties s390_cpu_index_to_props(MachineState *machine,
360 unsigned cpu_index)
361{
362 g_assert(machine->possible_cpus && cpu_index < machine->possible_cpus->len);
363
364 return machine->possible_cpus->cpus[cpu_index].props;
365}
366
367static const CPUArchIdList *s390_possible_cpu_arch_ids(MachineState *ms)
368{
369 int i;
370
371 if (ms->possible_cpus) {
372 g_assert(ms->possible_cpus && ms->possible_cpus->len == max_cpus);
373 return ms->possible_cpus;
374 }
375
376 ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
377 sizeof(CPUArchId) * max_cpus);
378 ms->possible_cpus->len = max_cpus;
379 for (i = 0; i < ms->possible_cpus->len; i++) {
380 ms->possible_cpus->cpus[i].vcpus_count = 1;
381 ms->possible_cpus->cpus[i].arch_id = i;
382 ms->possible_cpus->cpus[i].props.has_core_id = true;
383 ms->possible_cpus->cpus[i].props.core_id = i;
384 }
385
386 return ms->possible_cpus;
387}
388
502edbf8
MR
389static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
390 DeviceState *dev)
391{
392 if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
393 return HOTPLUG_HANDLER(machine);
394 }
395 return NULL;
396}
397
a006b67f
MR
398static void s390_hot_add_cpu(const int64_t id, Error **errp)
399{
400 MachineState *machine = MACHINE(qdev_get_machine());
a006b67f 401
6b62d961 402 s390x_new_cpu(machine->cpu_model, id, errp);
a006b67f
MR
403}
404
6286b419
DH
405static void s390_nmi(NMIState *n, int cpu_index, Error **errp)
406{
407 CPUState *cs = qemu_get_cpu(cpu_index);
408
409 if (s390_cpu_restart(S390_CPU(cs))) {
410 error_setg(errp, QERR_UNSUPPORTED);
411 }
412}
413
d07aa7c7
AK
414static void ccw_machine_class_init(ObjectClass *oc, void *data)
415{
416 MachineClass *mc = MACHINE_CLASS(oc);
3dd7852f 417 NMIClass *nc = NMI_CLASS(oc);
502edbf8 418 HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
9700230b 419 S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
d07aa7c7 420
9700230b 421 s390mc->ri_allowed = true;
e73316d5 422 s390mc->cpu_model_allowed = true;
e996583e 423 s390mc->css_migration_enabled = true;
62deb62d 424 s390mc->gs_allowed = true;
d07aa7c7 425 mc->init = ccw_init;
db3b2566 426 mc->reset = s390_machine_reset;
a006b67f 427 mc->hot_add_cpu = s390_hot_add_cpu;
d07aa7c7
AK
428 mc->block_default_type = IF_VIRTIO;
429 mc->no_cdrom = 1;
430 mc->no_floppy = 1;
431 mc->no_serial = 1;
432 mc->no_parallel = 1;
433 mc->no_sdcard = 1;
fb85b34d 434 mc->use_sclp = 1;
dcddc75e 435 mc->max_cpus = 248;
4dc3b151 436 mc->has_hotpluggable_cpus = true;
502edbf8 437 mc->get_hotplug_handler = s390_get_hotplug_handler;
4dc3b151
DH
438 mc->cpu_index_to_instance_props = s390_cpu_index_to_props;
439 mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids;
502edbf8 440 hc->plug = s390_machine_device_plug;
f2f3beb0 441 hc->unplug_request = s390_machine_device_unplug_request;
3dd7852f 442 nc->nmi_monitor_handler = s390_nmi;
d07aa7c7
AK
443}
444
2eb1cd07
TK
445static inline bool machine_get_aes_key_wrap(Object *obj, Error **errp)
446{
447 S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
448
449 return ms->aes_key_wrap;
450}
451
452static inline void machine_set_aes_key_wrap(Object *obj, bool value,
453 Error **errp)
454{
455 S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
456
457 ms->aes_key_wrap = value;
458}
459
460static inline bool machine_get_dea_key_wrap(Object *obj, Error **errp)
461{
462 S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
463
464 return ms->dea_key_wrap;
465}
466
467static inline void machine_set_dea_key_wrap(Object *obj, bool value,
468 Error **errp)
469{
470 S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
471
472 ms->dea_key_wrap = value;
473}
474
cec8bbf7 475static S390CcwMachineClass *current_mc;
9700230b 476
cec8bbf7
HP
477static S390CcwMachineClass *get_machine_class(void)
478{
479 if (unlikely(!current_mc)) {
392529cb 480 /*
cec8bbf7
HP
481 * No s390 ccw machine was instantiated, we are likely to
482 * be called for the 'none' machine. The properties will
483 * have their after-initialization values.
484 */
485 current_mc = S390_MACHINE_CLASS(
486 object_class_by_name(TYPE_S390_CCW_MACHINE));
9700230b 487 }
cec8bbf7 488 return current_mc;
9700230b
FZ
489}
490
cec8bbf7 491bool ri_allowed(void)
e73316d5 492{
cec8bbf7
HP
493 /* for "none" machine this results in true */
494 return get_machine_class()->ri_allowed;
495}
496
497bool cpu_model_allowed(void)
498{
499 /* for "none" machine this results in true */
500 return get_machine_class()->cpu_model_allowed;
e73316d5
CB
501}
502
62deb62d
FZ
503bool gs_allowed(void)
504{
c50f6511
DH
505 /* for "none" machine this results in true */
506 return get_machine_class()->gs_allowed;
62deb62d
FZ
507}
508
7104bae9
FA
509static char *machine_get_loadparm(Object *obj, Error **errp)
510{
511 S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
512
513 return g_memdup(ms->loadparm, sizeof(ms->loadparm));
514}
515
516static void machine_set_loadparm(Object *obj, const char *val, Error **errp)
517{
518 S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
519 int i;
520
521 for (i = 0; i < sizeof(ms->loadparm) && val[i]; i++) {
95a5befc 522 uint8_t c = qemu_toupper(val[i]); /* mimic HMC */
7104bae9
FA
523
524 if (('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || (c == '.') ||
525 (c == ' ')) {
526 ms->loadparm[i] = c;
527 } else {
528 error_setg(errp, "LOADPARM: invalid character '%c' (ASCII 0x%02x)",
529 c, c);
530 return;
531 }
532 }
533
534 for (; i < sizeof(ms->loadparm); i++) {
535 ms->loadparm[i] = ' '; /* pad right with spaces */
536 }
537}
274250c3
XFR
538static inline bool machine_get_squash_mcss(Object *obj, Error **errp)
539{
540 S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
541
542 return ms->s390_squash_mcss;
543}
544
545static inline void machine_set_squash_mcss(Object *obj, bool value,
546 Error **errp)
547{
548 S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
549
550 ms->s390_squash_mcss = value;
551}
7104bae9 552
2eb1cd07
TK
553static inline void s390_machine_initfn(Object *obj)
554{
555 object_property_add_bool(obj, "aes-key-wrap",
556 machine_get_aes_key_wrap,
557 machine_set_aes_key_wrap, NULL);
558 object_property_set_description(obj, "aes-key-wrap",
559 "enable/disable AES key wrapping using the CPACF wrapping key",
560 NULL);
561 object_property_set_bool(obj, true, "aes-key-wrap", NULL);
562
563 object_property_add_bool(obj, "dea-key-wrap",
564 machine_get_dea_key_wrap,
565 machine_set_dea_key_wrap, NULL);
566 object_property_set_description(obj, "dea-key-wrap",
567 "enable/disable DEA key wrapping using the CPACF wrapping key",
568 NULL);
569 object_property_set_bool(obj, true, "dea-key-wrap", NULL);
7104bae9
FA
570 object_property_add_str(obj, "loadparm",
571 machine_get_loadparm, machine_set_loadparm, NULL);
572 object_property_set_description(obj, "loadparm",
573 "Up to 8 chars in set of [A-Za-z0-9. ] (lower case chars converted"
574 " to upper case) to pass to machine loader, boot manager,"
575 " and guest kernel",
576 NULL);
274250c3
XFR
577 object_property_add_bool(obj, "s390-squash-mcss",
578 machine_get_squash_mcss,
579 machine_set_squash_mcss, NULL);
580 object_property_set_description(obj, "s390-squash-mcss",
581 "enable/disable squashing subchannels into the default css",
582 NULL);
583 object_property_set_bool(obj, false, "s390-squash-mcss", NULL);
2eb1cd07
TK
584}
585
d07aa7c7
AK
586static const TypeInfo ccw_machine_info = {
587 .name = TYPE_S390_CCW_MACHINE,
588 .parent = TYPE_MACHINE,
c4d3c0a2 589 .abstract = true,
2eb1cd07
TK
590 .instance_size = sizeof(S390CcwMachineState),
591 .instance_init = s390_machine_initfn,
9700230b 592 .class_size = sizeof(S390CcwMachineClass),
d07aa7c7 593 .class_init = ccw_machine_class_init,
3dd7852f
AK
594 .interfaces = (InterfaceInfo[]) {
595 { TYPE_NMI },
502edbf8 596 { TYPE_HOTPLUG_HANDLER},
3dd7852f
AK
597 { }
598 },
a5c95808
CH
599};
600
52629b3b
HP
601bool css_migration_enabled(void)
602{
603 return get_machine_class()->css_migration_enabled;
604}
605
4fca6548
JF
606#define DEFINE_CCW_MACHINE(suffix, verstr, latest) \
607 static void ccw_machine_##suffix##_class_init(ObjectClass *oc, \
608 void *data) \
609 { \
610 MachineClass *mc = MACHINE_CLASS(oc); \
611 ccw_machine_##suffix##_class_options(mc); \
612 mc->desc = "VirtIO-ccw based S390 machine v" verstr; \
613 if (latest) { \
614 mc->alias = "s390-ccw-virtio"; \
615 mc->is_default = 1; \
616 } \
617 } \
618 static void ccw_machine_##suffix##_instance_init(Object *obj) \
619 { \
620 MachineState *machine = MACHINE(obj); \
cec8bbf7 621 current_mc = S390_MACHINE_CLASS(MACHINE_GET_CLASS(machine)); \
4fca6548
JF
622 ccw_machine_##suffix##_instance_options(machine); \
623 } \
624 static const TypeInfo ccw_machine_##suffix##_info = { \
625 .name = MACHINE_TYPE_NAME("s390-ccw-virtio-" verstr), \
626 .parent = TYPE_S390_CCW_MACHINE, \
627 .class_init = ccw_machine_##suffix##_class_init, \
628 .instance_init = ccw_machine_##suffix##_instance_init, \
629 }; \
630 static void ccw_machine_register_##suffix(void) \
631 { \
632 type_register_static(&ccw_machine_##suffix##_info); \
633 } \
0e6aac87 634 type_init(ccw_machine_register_##suffix)
4fca6548 635
70d8d9a0
CH
636#define CCW_COMPAT_2_10 \
637 HW_COMPAT_2_10
638
10890873 639#define CCW_COMPAT_2_9 \
903fd80b
CI
640 HW_COMPAT_2_9 \
641 {\
642 .driver = TYPE_S390_STATTRIB,\
643 .property = "migration-enabled",\
644 .value = "off",\
645 },
10890873 646
113725a6 647#define CCW_COMPAT_2_8 \
069097da
HP
648 HW_COMPAT_2_8 \
649 {\
650 .driver = TYPE_S390_FLIC_COMMON,\
651 .property = "adapter_routes_max_batch",\
652 .value = "64",\
653 },
113725a6 654
61823988
CH
655#define CCW_COMPAT_2_7 \
656 HW_COMPAT_2_7
657
946e55f3 658#define CCW_COMPAT_2_6 \
04ca4b92
AY
659 HW_COMPAT_2_6 \
660 {\
661 .driver = TYPE_S390_IPL,\
662 .property = "iplbext_migration",\
663 .value = "off",\
2a79eb1a
CH
664 }, {\
665 .driver = TYPE_VIRTUAL_CSS_BRIDGE,\
666 .property = "css_dev_path",\
667 .value = "off",\
04ca4b92 668 },
946e55f3 669
cf87e0a3
SL
670#define CCW_COMPAT_2_5 \
671 HW_COMPAT_2_5
672
9ef40173 673#define CCW_COMPAT_2_4 \
54d8ec84 674 HW_COMPAT_2_4 \
9ef40173
JH
675 {\
676 .driver = TYPE_S390_SKEYS,\
677 .property = "migration-enabled",\
678 .value = "off",\
542571d5
CH
679 },{\
680 .driver = "virtio-blk-ccw",\
681 .property = "max_revision",\
682 .value = "0",\
683 },{\
684 .driver = "virtio-balloon-ccw",\
685 .property = "max_revision",\
686 .value = "0",\
687 },{\
688 .driver = "virtio-serial-ccw",\
689 .property = "max_revision",\
690 .value = "0",\
691 },{\
692 .driver = "virtio-9p-ccw",\
693 .property = "max_revision",\
694 .value = "0",\
695 },{\
696 .driver = "virtio-rng-ccw",\
697 .property = "max_revision",\
698 .value = "0",\
085b0b05
CH
699 },{\
700 .driver = "virtio-net-ccw",\
701 .property = "max_revision",\
702 .value = "0",\
703 },{\
704 .driver = "virtio-scsi-ccw",\
705 .property = "max_revision",\
706 .value = "0",\
707 },{\
708 .driver = "vhost-scsi-ccw",\
709 .property = "max_revision",\
710 .value = "0",\
9ef40173
JH
711 },
712
70d8d9a0
CH
713static void ccw_machine_2_11_instance_options(MachineState *machine)
714{
715}
716
717static void ccw_machine_2_11_class_options(MachineClass *mc)
718{
719}
720DEFINE_CCW_MACHINE(2_11, "2.11", true);
721
10890873
CH
722static void ccw_machine_2_10_instance_options(MachineState *machine)
723{
70d8d9a0 724 ccw_machine_2_11_instance_options(machine);
e996583e
HP
725 if (css_migration_enabled()) {
726 css_register_vmstate();
727 }
10890873
CH
728}
729
730static void ccw_machine_2_10_class_options(MachineClass *mc)
731{
70d8d9a0
CH
732 ccw_machine_2_11_class_options(mc);
733 SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_10);
10890873 734}
70d8d9a0 735DEFINE_CCW_MACHINE(2_10, "2.10", false);
10890873 736
113725a6
CH
737static void ccw_machine_2_9_instance_options(MachineState *machine)
738{
10890873 739 ccw_machine_2_10_instance_options(machine);
7223bcce
JH
740 s390_cpudef_featoff_greater(12, 1, S390_FEAT_ESOP);
741 s390_cpudef_featoff_greater(12, 1, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2);
3b00f702
YMZ
742 s390_cpudef_featoff_greater(12, 1, S390_FEAT_ZPCI);
743 s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_INT_SUPPRESSION);
744 s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_EVENT_NOTIFICATION);
113725a6
CH
745}
746
747static void ccw_machine_2_9_class_options(MachineClass *mc)
748{
52629b3b
HP
749 S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
750
62deb62d 751 s390mc->gs_allowed = false;
10890873
CH
752 ccw_machine_2_10_class_options(mc);
753 SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_9);
52629b3b 754 s390mc->css_migration_enabled = false;
113725a6 755}
10890873 756DEFINE_CCW_MACHINE(2_9, "2.9", false);
113725a6 757
61823988
CH
758static void ccw_machine_2_8_instance_options(MachineState *machine)
759{
113725a6 760 ccw_machine_2_9_instance_options(machine);
61823988
CH
761}
762
763static void ccw_machine_2_8_class_options(MachineClass *mc)
764{
113725a6
CH
765 ccw_machine_2_9_class_options(mc);
766 SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_8);
61823988 767}
113725a6 768DEFINE_CCW_MACHINE(2_8, "2.8", false);
61823988 769
946e55f3
CH
770static void ccw_machine_2_7_instance_options(MachineState *machine)
771{
61823988 772 ccw_machine_2_8_instance_options(machine);
946e55f3
CH
773}
774
775static void ccw_machine_2_7_class_options(MachineClass *mc)
776{
e73316d5
CB
777 S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
778
779 s390mc->cpu_model_allowed = false;
61823988
CH
780 ccw_machine_2_8_class_options(mc);
781 SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_7);
946e55f3 782}
61823988 783DEFINE_CCW_MACHINE(2_7, "2.7", false);
946e55f3 784
4fca6548 785static void ccw_machine_2_6_instance_options(MachineState *machine)
c4d3c0a2 786{
946e55f3 787 ccw_machine_2_7_instance_options(machine);
c4d3c0a2
CB
788}
789
4fca6548 790static void ccw_machine_2_6_class_options(MachineClass *mc)
84b48ad6 791{
9700230b
FZ
792 S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
793
794 s390mc->ri_allowed = false;
946e55f3
CH
795 ccw_machine_2_7_class_options(mc);
796 SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_6);
84b48ad6 797}
946e55f3 798DEFINE_CCW_MACHINE(2_6, "2.6", false);
84b48ad6 799
4fca6548
JF
800static void ccw_machine_2_5_instance_options(MachineState *machine)
801{
946e55f3 802 ccw_machine_2_6_instance_options(machine);
4fca6548 803}
84b48ad6 804
4fca6548 805static void ccw_machine_2_5_class_options(MachineClass *mc)
b21b7598 806{
946e55f3 807 ccw_machine_2_6_class_options(mc);
4fca6548
JF
808 SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_5);
809}
810DEFINE_CCW_MACHINE(2_5, "2.5", false);
b21b7598 811
4fca6548
JF
812static void ccw_machine_2_4_instance_options(MachineState *machine)
813{
814 ccw_machine_2_5_instance_options(machine);
b21b7598
CH
815}
816
4fca6548
JF
817static void ccw_machine_2_4_class_options(MachineClass *mc)
818{
946e55f3 819 ccw_machine_2_5_class_options(mc);
4fca6548
JF
820 SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_4);
821}
822DEFINE_CCW_MACHINE(2_4, "2.4", false);
b21b7598 823
d07aa7c7 824static void ccw_machine_register_types(void)
a5c95808 825{
d07aa7c7 826 type_register_static(&ccw_machine_info);
a5c95808
CH
827}
828
d07aa7c7 829type_init(ccw_machine_register_types)