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 | |
45 | S390CPU *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 | |
61 | static 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 | |
73 | out: |
74 | object_unref(OBJECT(cpu)); |
75 | if (err) { |
76 | error_propagate(errp, err); |
77 | cpu = NULL; |
78 | } |
79 | return cpu; |
80 | } |
81 | |
82 | static 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 | |
95 | static const char *const reset_dev_types[] = { |
96 | TYPE_VIRTUAL_CSS_BRIDGE, |
97 | "s390-sclp-event-facility" , |
98 | "s390-flic" , |
99 | "diag288" , |
100 | }; |
101 | |
102 | static 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 | |
115 | static 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 | |
137 | static 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 | |
148 | static 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) |
166 | static 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 | |
206 | static 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 | |
235 | static 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 | |
255 | static 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 | |
264 | static 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 | |
323 | static 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 | |
337 | static 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 | |
345 | static 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 | |
387 | static 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 | |
395 | static 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 | |
404 | static 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 | |
414 | static 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 | |
438 | static 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 | |
447 | static 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 | |
458 | static 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 | |
465 | static 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 | |
497 | static 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 | |
504 | static 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 | |
512 | static 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 | |
519 | static 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 | |
527 | static S390CcwMachineClass *current_mc; |
528 | |
529 | static 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 | |
543 | bool ri_allowed(void) |
544 | { |
545 | /* for "none" machine this results in true */ |
546 | return get_machine_class()->ri_allowed; |
547 | } |
548 | |
549 | bool cpu_model_allowed(void) |
550 | { |
551 | /* for "none" machine this results in true */ |
552 | return get_machine_class()->cpu_model_allowed; |
553 | } |
554 | |
555 | bool hpage_1m_allowed(void) |
556 | { |
557 | /* for "none" machine this results in true */ |
558 | return get_machine_class()->hpage_1m_allowed; |
559 | } |
560 | |
561 | static 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 | |
568 | static 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 | } |
590 | static 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 | |
616 | static 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 | |
631 | bool 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 | |
666 | static void ccw_machine_4_2_instance_options(MachineState *machine) |
667 | { |
668 | } |
669 | |
670 | static void ccw_machine_4_2_class_options(MachineClass *mc) |
671 | { |
672 | } |
673 | DEFINE_CCW_MACHINE(4_2, "4.2" , true); |
674 | |
675 | static void ccw_machine_4_1_instance_options(MachineState *machine) |
676 | { |
677 | ccw_machine_4_2_instance_options(machine); |
678 | } |
679 | |
680 | static 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 | } |
685 | DEFINE_CCW_MACHINE(4_1, "4.1" , false); |
686 | |
687 | static 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 | |
694 | static 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 | } |
699 | DEFINE_CCW_MACHINE(4_0, "4.0" , false); |
700 | |
701 | static 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 | |
710 | static 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 | } |
715 | DEFINE_CCW_MACHINE(3_1, "3.1" , false); |
716 | |
717 | static void ccw_machine_3_0_instance_options(MachineState *machine) |
718 | { |
719 | ccw_machine_3_1_instance_options(machine); |
720 | } |
721 | |
722 | static 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 | } |
730 | DEFINE_CCW_MACHINE(3_0, "3.0" , false); |
731 | |
732 | static 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 | |
739 | static 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 | } |
744 | DEFINE_CCW_MACHINE(2_12, "2.12" , false); |
745 | |
746 | static 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 | |
755 | static 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 | } |
765 | DEFINE_CCW_MACHINE(2_11, "2.11" , false); |
766 | |
767 | static void ccw_machine_2_10_instance_options(MachineState *machine) |
768 | { |
769 | ccw_machine_2_11_instance_options(machine); |
770 | } |
771 | |
772 | static 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 | } |
777 | DEFINE_CCW_MACHINE(2_10, "2.10" , false); |
778 | |
779 | static 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 | |
789 | static 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 | } |
801 | DEFINE_CCW_MACHINE(2_9, "2.9" , false); |
802 | |
803 | static void ccw_machine_2_8_instance_options(MachineState *machine) |
804 | { |
805 | ccw_machine_2_9_instance_options(machine); |
806 | } |
807 | |
808 | static 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 | } |
818 | DEFINE_CCW_MACHINE(2_8, "2.8" , false); |
819 | |
820 | static void ccw_machine_2_7_instance_options(MachineState *machine) |
821 | { |
822 | ccw_machine_2_8_instance_options(machine); |
823 | } |
824 | |
825 | static 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 | } |
833 | DEFINE_CCW_MACHINE(2_7, "2.7" , false); |
834 | |
835 | static void ccw_machine_2_6_instance_options(MachineState *machine) |
836 | { |
837 | ccw_machine_2_7_instance_options(machine); |
838 | } |
839 | |
840 | static 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 | } |
853 | DEFINE_CCW_MACHINE(2_6, "2.6" , false); |
854 | |
855 | static void ccw_machine_2_5_instance_options(MachineState *machine) |
856 | { |
857 | ccw_machine_2_6_instance_options(machine); |
858 | } |
859 | |
860 | static 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 | } |
865 | DEFINE_CCW_MACHINE(2_5, "2.5" , false); |
866 | |
867 | static void ccw_machine_2_4_instance_options(MachineState *machine) |
868 | { |
869 | ccw_machine_2_5_instance_options(machine); |
870 | } |
871 | |
872 | static 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 | } |
890 | DEFINE_CCW_MACHINE(2_4, "2.4" , false); |
891 | |
892 | static void ccw_machine_register_types(void) |
893 | { |
894 | type_register_static(&ccw_machine_info); |
895 | } |
896 | |
897 | type_init(ccw_machine_register_types) |
898 | |