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