xref: /openbmc/qemu/hw/core/machine.c (revision 2f99b9c273ded76211ddb445b273ce854d469033)
1 /*
2  * QEMU Machine
3  *
4  * Copyright (C) 2014 Red Hat Inc
5  *
6  * Authors:
7  *   Marcel Apfelbaum <marcel.a@redhat.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  */
12 
13 #include "qemu/osdep.h"
14 #include "qemu/units.h"
15 #include "hw/boards.h"
16 #include "qapi/error.h"
17 #include "qapi/qapi-visit-common.h"
18 #include "qapi/visitor.h"
19 #include "hw/sysbus.h"
20 #include "sysemu/sysemu.h"
21 #include "sysemu/numa.h"
22 #include "qemu/error-report.h"
23 #include "sysemu/qtest.h"
24 #include "hw/pci/pci.h"
25 
26 GlobalProperty hw_compat_3_1[] = {
27     {
28         .driver   = "pcie-root-port",
29         .property = "x-speed",
30         .value    = "2_5",
31     },{
32         .driver   = "pcie-root-port",
33         .property = "x-width",
34         .value    = "1",
35     },
36 };
37 const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1);
38 
39 GlobalProperty hw_compat_3_0[] = {};
40 const size_t hw_compat_3_0_len = G_N_ELEMENTS(hw_compat_3_0);
41 
42 GlobalProperty hw_compat_2_12[] = {
43     {
44         .driver   = "migration",
45         .property = "decompress-error-check",
46         .value    = "off",
47     },{
48         .driver   = "hda-audio",
49         .property = "use-timer",
50         .value    = "false",
51     },{
52         .driver   = "cirrus-vga",
53         .property = "global-vmstate",
54         .value    = "true",
55     },{
56         .driver   = "VGA",
57         .property = "global-vmstate",
58         .value    = "true",
59     },{
60         .driver   = "vmware-svga",
61         .property = "global-vmstate",
62         .value    = "true",
63     },{
64         .driver   = "qxl-vga",
65         .property = "global-vmstate",
66         .value    = "true",
67     },
68 };
69 const size_t hw_compat_2_12_len = G_N_ELEMENTS(hw_compat_2_12);
70 
71 GlobalProperty hw_compat_2_11[] = {
72     {
73         .driver   = "hpet",
74         .property = "hpet-offset-saved",
75         .value    = "false",
76     },{
77         .driver   = "virtio-blk-pci",
78         .property = "vectors",
79         .value    = "2",
80     },{
81         .driver   = "vhost-user-blk-pci",
82         .property = "vectors",
83         .value    = "2",
84     },{
85         .driver   = "e1000",
86         .property = "migrate_tso_props",
87         .value    = "off",
88     },
89 };
90 const size_t hw_compat_2_11_len = G_N_ELEMENTS(hw_compat_2_11);
91 
92 GlobalProperty hw_compat_2_10[] = {
93     {
94         .driver   = "virtio-mouse-device",
95         .property = "wheel-axis",
96         .value    = "false",
97     },{
98         .driver   = "virtio-tablet-device",
99         .property = "wheel-axis",
100         .value    = "false",
101     },
102 };
103 const size_t hw_compat_2_10_len = G_N_ELEMENTS(hw_compat_2_10);
104 
105 GlobalProperty hw_compat_2_9[] = {
106     {
107         .driver   = "pci-bridge",
108         .property = "shpc",
109         .value    = "off",
110     },{
111         .driver   = "intel-iommu",
112         .property = "pt",
113         .value    = "off",
114     },{
115         .driver   = "virtio-net-device",
116         .property = "x-mtu-bypass-backend",
117         .value    = "off",
118     },{
119         .driver   = "pcie-root-port",
120         .property = "x-migrate-msix",
121         .value    = "false",
122     },
123 };
124 const size_t hw_compat_2_9_len = G_N_ELEMENTS(hw_compat_2_9);
125 
126 GlobalProperty hw_compat_2_8[] = {
127     {
128         .driver   = "fw_cfg_mem",
129         .property = "x-file-slots",
130         .value    = stringify(0x10),
131     },{
132         .driver   = "fw_cfg_io",
133         .property = "x-file-slots",
134         .value    = stringify(0x10),
135     },{
136         .driver   = "pflash_cfi01",
137         .property = "old-multiple-chip-handling",
138         .value    = "on",
139     },{
140         .driver   = "pci-bridge",
141         .property = "shpc",
142         .value    = "on",
143     },{
144         .driver   = TYPE_PCI_DEVICE,
145         .property = "x-pcie-extcap-init",
146         .value    = "off",
147     },{
148         .driver   = "virtio-pci",
149         .property = "x-pcie-deverr-init",
150         .value    = "off",
151     },{
152         .driver   = "virtio-pci",
153         .property = "x-pcie-lnkctl-init",
154         .value    = "off",
155     },{
156         .driver   = "virtio-pci",
157         .property = "x-pcie-pm-init",
158         .value    = "off",
159     },{
160         .driver   = "cirrus-vga",
161         .property = "vgamem_mb",
162         .value    = "8",
163     },{
164         .driver   = "isa-cirrus-vga",
165         .property = "vgamem_mb",
166         .value    = "8",
167     },
168 };
169 const size_t hw_compat_2_8_len = G_N_ELEMENTS(hw_compat_2_8);
170 
171 GlobalProperty hw_compat_2_7[] = {
172     {
173         .driver   = "virtio-pci",
174         .property = "page-per-vq",
175         .value    = "on",
176     },{
177         .driver   = "virtio-serial-device",
178         .property = "emergency-write",
179         .value    = "off",
180     },{
181         .driver   = "ioapic",
182         .property = "version",
183         .value    = "0x11",
184     },{
185         .driver   = "intel-iommu",
186         .property = "x-buggy-eim",
187         .value    = "true",
188     },{
189         .driver   = "virtio-pci",
190         .property = "x-ignore-backend-features",
191         .value    = "on",
192     },
193 };
194 const size_t hw_compat_2_7_len = G_N_ELEMENTS(hw_compat_2_7);
195 
196 GlobalProperty hw_compat_2_6[] = {
197     {
198         .driver   = "virtio-mmio",
199         .property = "format_transport_address",
200         .value    = "off",
201     },{
202         .driver   = "virtio-pci",
203         .property = "disable-modern",
204         .value    = "on",
205     },{
206         .driver   = "virtio-pci",
207         .property = "disable-legacy",
208         .value    = "off",
209     },
210 };
211 const size_t hw_compat_2_6_len = G_N_ELEMENTS(hw_compat_2_6);
212 
213 GlobalProperty hw_compat_2_5[] = {
214     {
215         .driver   = "isa-fdc",
216         .property = "fallback",
217         .value    = "144",
218     },{
219         .driver   = "pvscsi",
220         .property = "x-old-pci-configuration",
221         .value    = "on",
222     },{
223         .driver   = "pvscsi",
224         .property = "x-disable-pcie",
225         .value    = "on",
226     },
227     {
228         .driver   = "vmxnet3",
229         .property = "x-old-msi-offsets",
230         .value    = "on",
231     },{
232         .driver   = "vmxnet3",
233         .property = "x-disable-pcie",
234         .value    = "on",
235     },
236 };
237 const size_t hw_compat_2_5_len = G_N_ELEMENTS(hw_compat_2_5);
238 
239 GlobalProperty hw_compat_2_4[] = {
240     {
241         .driver   = "virtio-blk-device",
242         .property = "scsi",
243         .value    = "true",
244     },{
245         .driver   = "e1000",
246         .property = "extra_mac_registers",
247         .value    = "off",
248     },{
249         .driver   = "virtio-pci",
250         .property = "x-disable-pcie",
251         .value    = "on",
252     },{
253         .driver   = "virtio-pci",
254         .property = "migrate-extra",
255         .value    = "off",
256     },{
257         .driver   = "fw_cfg_mem",
258         .property = "dma_enabled",
259         .value    = "off",
260     },{
261         .driver   = "fw_cfg_io",
262         .property = "dma_enabled",
263         .value    = "off",
264     }
265 };
266 const size_t hw_compat_2_4_len = G_N_ELEMENTS(hw_compat_2_4);
267 
268 static char *machine_get_accel(Object *obj, Error **errp)
269 {
270     MachineState *ms = MACHINE(obj);
271 
272     return g_strdup(ms->accel);
273 }
274 
275 static void machine_set_accel(Object *obj, const char *value, Error **errp)
276 {
277     MachineState *ms = MACHINE(obj);
278 
279     g_free(ms->accel);
280     ms->accel = g_strdup(value);
281 }
282 
283 static void machine_set_kernel_irqchip(Object *obj, Visitor *v,
284                                        const char *name, void *opaque,
285                                        Error **errp)
286 {
287     Error *err = NULL;
288     MachineState *ms = MACHINE(obj);
289     OnOffSplit mode;
290 
291     visit_type_OnOffSplit(v, name, &mode, &err);
292     if (err) {
293         error_propagate(errp, err);
294         return;
295     } else {
296         switch (mode) {
297         case ON_OFF_SPLIT_ON:
298             ms->kernel_irqchip_allowed = true;
299             ms->kernel_irqchip_required = true;
300             ms->kernel_irqchip_split = false;
301             break;
302         case ON_OFF_SPLIT_OFF:
303             ms->kernel_irqchip_allowed = false;
304             ms->kernel_irqchip_required = false;
305             ms->kernel_irqchip_split = false;
306             break;
307         case ON_OFF_SPLIT_SPLIT:
308             ms->kernel_irqchip_allowed = true;
309             ms->kernel_irqchip_required = true;
310             ms->kernel_irqchip_split = true;
311             break;
312         default:
313             /* The value was checked in visit_type_OnOffSplit() above. If
314              * we get here, then something is wrong in QEMU.
315              */
316             abort();
317         }
318     }
319 }
320 
321 static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v,
322                                        const char *name, void *opaque,
323                                        Error **errp)
324 {
325     MachineState *ms = MACHINE(obj);
326     int64_t value = ms->kvm_shadow_mem;
327 
328     visit_type_int(v, name, &value, errp);
329 }
330 
331 static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v,
332                                        const char *name, void *opaque,
333                                        Error **errp)
334 {
335     MachineState *ms = MACHINE(obj);
336     Error *error = NULL;
337     int64_t value;
338 
339     visit_type_int(v, name, &value, &error);
340     if (error) {
341         error_propagate(errp, error);
342         return;
343     }
344 
345     ms->kvm_shadow_mem = value;
346 }
347 
348 static char *machine_get_kernel(Object *obj, Error **errp)
349 {
350     MachineState *ms = MACHINE(obj);
351 
352     return g_strdup(ms->kernel_filename);
353 }
354 
355 static void machine_set_kernel(Object *obj, const char *value, Error **errp)
356 {
357     MachineState *ms = MACHINE(obj);
358 
359     g_free(ms->kernel_filename);
360     ms->kernel_filename = g_strdup(value);
361 }
362 
363 static char *machine_get_initrd(Object *obj, Error **errp)
364 {
365     MachineState *ms = MACHINE(obj);
366 
367     return g_strdup(ms->initrd_filename);
368 }
369 
370 static void machine_set_initrd(Object *obj, const char *value, Error **errp)
371 {
372     MachineState *ms = MACHINE(obj);
373 
374     g_free(ms->initrd_filename);
375     ms->initrd_filename = g_strdup(value);
376 }
377 
378 static char *machine_get_append(Object *obj, Error **errp)
379 {
380     MachineState *ms = MACHINE(obj);
381 
382     return g_strdup(ms->kernel_cmdline);
383 }
384 
385 static void machine_set_append(Object *obj, const char *value, Error **errp)
386 {
387     MachineState *ms = MACHINE(obj);
388 
389     g_free(ms->kernel_cmdline);
390     ms->kernel_cmdline = g_strdup(value);
391 }
392 
393 static char *machine_get_dtb(Object *obj, Error **errp)
394 {
395     MachineState *ms = MACHINE(obj);
396 
397     return g_strdup(ms->dtb);
398 }
399 
400 static void machine_set_dtb(Object *obj, const char *value, Error **errp)
401 {
402     MachineState *ms = MACHINE(obj);
403 
404     g_free(ms->dtb);
405     ms->dtb = g_strdup(value);
406 }
407 
408 static char *machine_get_dumpdtb(Object *obj, Error **errp)
409 {
410     MachineState *ms = MACHINE(obj);
411 
412     return g_strdup(ms->dumpdtb);
413 }
414 
415 static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp)
416 {
417     MachineState *ms = MACHINE(obj);
418 
419     g_free(ms->dumpdtb);
420     ms->dumpdtb = g_strdup(value);
421 }
422 
423 static void machine_get_phandle_start(Object *obj, Visitor *v,
424                                       const char *name, void *opaque,
425                                       Error **errp)
426 {
427     MachineState *ms = MACHINE(obj);
428     int64_t value = ms->phandle_start;
429 
430     visit_type_int(v, name, &value, errp);
431 }
432 
433 static void machine_set_phandle_start(Object *obj, Visitor *v,
434                                       const char *name, void *opaque,
435                                       Error **errp)
436 {
437     MachineState *ms = MACHINE(obj);
438     Error *error = NULL;
439     int64_t value;
440 
441     visit_type_int(v, name, &value, &error);
442     if (error) {
443         error_propagate(errp, error);
444         return;
445     }
446 
447     ms->phandle_start = value;
448 }
449 
450 static char *machine_get_dt_compatible(Object *obj, Error **errp)
451 {
452     MachineState *ms = MACHINE(obj);
453 
454     return g_strdup(ms->dt_compatible);
455 }
456 
457 static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp)
458 {
459     MachineState *ms = MACHINE(obj);
460 
461     g_free(ms->dt_compatible);
462     ms->dt_compatible = g_strdup(value);
463 }
464 
465 static bool machine_get_dump_guest_core(Object *obj, Error **errp)
466 {
467     MachineState *ms = MACHINE(obj);
468 
469     return ms->dump_guest_core;
470 }
471 
472 static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp)
473 {
474     MachineState *ms = MACHINE(obj);
475 
476     ms->dump_guest_core = value;
477 }
478 
479 static bool machine_get_mem_merge(Object *obj, Error **errp)
480 {
481     MachineState *ms = MACHINE(obj);
482 
483     return ms->mem_merge;
484 }
485 
486 static void machine_set_mem_merge(Object *obj, bool value, Error **errp)
487 {
488     MachineState *ms = MACHINE(obj);
489 
490     ms->mem_merge = value;
491 }
492 
493 static bool machine_get_usb(Object *obj, Error **errp)
494 {
495     MachineState *ms = MACHINE(obj);
496 
497     return ms->usb;
498 }
499 
500 static void machine_set_usb(Object *obj, bool value, Error **errp)
501 {
502     MachineState *ms = MACHINE(obj);
503 
504     ms->usb = value;
505     ms->usb_disabled = !value;
506 }
507 
508 static bool machine_get_graphics(Object *obj, Error **errp)
509 {
510     MachineState *ms = MACHINE(obj);
511 
512     return ms->enable_graphics;
513 }
514 
515 static void machine_set_graphics(Object *obj, bool value, Error **errp)
516 {
517     MachineState *ms = MACHINE(obj);
518 
519     ms->enable_graphics = value;
520 }
521 
522 static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp)
523 {
524     MachineState *ms = MACHINE(obj);
525 
526     return ms->igd_gfx_passthru;
527 }
528 
529 static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
530 {
531     MachineState *ms = MACHINE(obj);
532 
533     ms->igd_gfx_passthru = value;
534 }
535 
536 static char *machine_get_firmware(Object *obj, Error **errp)
537 {
538     MachineState *ms = MACHINE(obj);
539 
540     return g_strdup(ms->firmware);
541 }
542 
543 static void machine_set_firmware(Object *obj, const char *value, Error **errp)
544 {
545     MachineState *ms = MACHINE(obj);
546 
547     g_free(ms->firmware);
548     ms->firmware = g_strdup(value);
549 }
550 
551 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
552 {
553     MachineState *ms = MACHINE(obj);
554 
555     ms->suppress_vmdesc = value;
556 }
557 
558 static bool machine_get_suppress_vmdesc(Object *obj, Error **errp)
559 {
560     MachineState *ms = MACHINE(obj);
561 
562     return ms->suppress_vmdesc;
563 }
564 
565 static void machine_set_enforce_config_section(Object *obj, bool value,
566                                              Error **errp)
567 {
568     MachineState *ms = MACHINE(obj);
569 
570     warn_report("enforce-config-section is deprecated, please use "
571                 "-global migration.send-configuration=on|off instead");
572 
573     ms->enforce_config_section = value;
574 }
575 
576 static bool machine_get_enforce_config_section(Object *obj, Error **errp)
577 {
578     MachineState *ms = MACHINE(obj);
579 
580     return ms->enforce_config_section;
581 }
582 
583 static char *machine_get_memory_encryption(Object *obj, Error **errp)
584 {
585     MachineState *ms = MACHINE(obj);
586 
587     return g_strdup(ms->memory_encryption);
588 }
589 
590 static void machine_set_memory_encryption(Object *obj, const char *value,
591                                         Error **errp)
592 {
593     MachineState *ms = MACHINE(obj);
594 
595     g_free(ms->memory_encryption);
596     ms->memory_encryption = g_strdup(value);
597 }
598 
599 void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type)
600 {
601     strList *item = g_new0(strList, 1);
602 
603     item->value = g_strdup(type);
604     item->next = mc->allowed_dynamic_sysbus_devices;
605     mc->allowed_dynamic_sysbus_devices = item;
606 }
607 
608 static void validate_sysbus_device(SysBusDevice *sbdev, void *opaque)
609 {
610     MachineState *machine = opaque;
611     MachineClass *mc = MACHINE_GET_CLASS(machine);
612     bool allowed = false;
613     strList *wl;
614 
615     for (wl = mc->allowed_dynamic_sysbus_devices;
616          !allowed && wl;
617          wl = wl->next) {
618         allowed |= !!object_dynamic_cast(OBJECT(sbdev), wl->value);
619     }
620 
621     if (!allowed) {
622         error_report("Option '-device %s' cannot be handled by this machine",
623                      object_class_get_name(object_get_class(OBJECT(sbdev))));
624         exit(1);
625     }
626 }
627 
628 static void machine_init_notify(Notifier *notifier, void *data)
629 {
630     MachineState *machine = MACHINE(qdev_get_machine());
631 
632     /*
633      * Loop through all dynamically created sysbus devices and check if they are
634      * all allowed.  If a device is not allowed, error out.
635      */
636     foreach_dynamic_sysbus_device(validate_sysbus_device, machine);
637 }
638 
639 HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine)
640 {
641     int i;
642     HotpluggableCPUList *head = NULL;
643     MachineClass *mc = MACHINE_GET_CLASS(machine);
644 
645     /* force board to initialize possible_cpus if it hasn't been done yet */
646     mc->possible_cpu_arch_ids(machine);
647 
648     for (i = 0; i < machine->possible_cpus->len; i++) {
649         Object *cpu;
650         HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1);
651         HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1);
652 
653         cpu_item->type = g_strdup(machine->possible_cpus->cpus[i].type);
654         cpu_item->vcpus_count = machine->possible_cpus->cpus[i].vcpus_count;
655         cpu_item->props = g_memdup(&machine->possible_cpus->cpus[i].props,
656                                    sizeof(*cpu_item->props));
657 
658         cpu = machine->possible_cpus->cpus[i].cpu;
659         if (cpu) {
660             cpu_item->has_qom_path = true;
661             cpu_item->qom_path = object_get_canonical_path(cpu);
662         }
663         list_item->value = cpu_item;
664         list_item->next = head;
665         head = list_item;
666     }
667     return head;
668 }
669 
670 /**
671  * machine_set_cpu_numa_node:
672  * @machine: machine object to modify
673  * @props: specifies which cpu objects to assign to
674  *         numa node specified by @props.node_id
675  * @errp: if an error occurs, a pointer to an area to store the error
676  *
677  * Associate NUMA node specified by @props.node_id with cpu slots that
678  * match socket/core/thread-ids specified by @props. It's recommended to use
679  * query-hotpluggable-cpus.props values to specify affected cpu slots,
680  * which would lead to exact 1:1 mapping of cpu slots to NUMA node.
681  *
682  * However for CLI convenience it's possible to pass in subset of properties,
683  * which would affect all cpu slots that match it.
684  * Ex for pc machine:
685  *    -smp 4,cores=2,sockets=2 -numa node,nodeid=0 -numa node,nodeid=1 \
686  *    -numa cpu,node-id=0,socket_id=0 \
687  *    -numa cpu,node-id=1,socket_id=1
688  * will assign all child cores of socket 0 to node 0 and
689  * of socket 1 to node 1.
690  *
691  * On attempt of reassigning (already assigned) cpu slot to another NUMA node,
692  * return error.
693  * Empty subset is disallowed and function will return with error in this case.
694  */
695 void machine_set_cpu_numa_node(MachineState *machine,
696                                const CpuInstanceProperties *props, Error **errp)
697 {
698     MachineClass *mc = MACHINE_GET_CLASS(machine);
699     bool match = false;
700     int i;
701 
702     if (!mc->possible_cpu_arch_ids) {
703         error_setg(errp, "mapping of CPUs to NUMA node is not supported");
704         return;
705     }
706 
707     /* disabling node mapping is not supported, forbid it */
708     assert(props->has_node_id);
709 
710     /* force board to initialize possible_cpus if it hasn't been done yet */
711     mc->possible_cpu_arch_ids(machine);
712 
713     for (i = 0; i < machine->possible_cpus->len; i++) {
714         CPUArchId *slot = &machine->possible_cpus->cpus[i];
715 
716         /* reject unsupported by board properties */
717         if (props->has_thread_id && !slot->props.has_thread_id) {
718             error_setg(errp, "thread-id is not supported");
719             return;
720         }
721 
722         if (props->has_core_id && !slot->props.has_core_id) {
723             error_setg(errp, "core-id is not supported");
724             return;
725         }
726 
727         if (props->has_socket_id && !slot->props.has_socket_id) {
728             error_setg(errp, "socket-id is not supported");
729             return;
730         }
731 
732         /* skip slots with explicit mismatch */
733         if (props->has_thread_id && props->thread_id != slot->props.thread_id) {
734                 continue;
735         }
736 
737         if (props->has_core_id && props->core_id != slot->props.core_id) {
738                 continue;
739         }
740 
741         if (props->has_socket_id && props->socket_id != slot->props.socket_id) {
742                 continue;
743         }
744 
745         /* reject assignment if slot is already assigned, for compatibility
746          * of legacy cpu_index mapping with SPAPR core based mapping do not
747          * error out if cpu thread and matched core have the same node-id */
748         if (slot->props.has_node_id &&
749             slot->props.node_id != props->node_id) {
750             error_setg(errp, "CPU is already assigned to node-id: %" PRId64,
751                        slot->props.node_id);
752             return;
753         }
754 
755         /* assign slot to node as it's matched '-numa cpu' key */
756         match = true;
757         slot->props.node_id = props->node_id;
758         slot->props.has_node_id = props->has_node_id;
759     }
760 
761     if (!match) {
762         error_setg(errp, "no match found");
763     }
764 }
765 
766 static void machine_class_init(ObjectClass *oc, void *data)
767 {
768     MachineClass *mc = MACHINE_CLASS(oc);
769 
770     /* Default 128 MB as guest ram size */
771     mc->default_ram_size = 128 * MiB;
772     mc->rom_file_has_mr = true;
773 
774     /* numa node memory size aligned on 8MB by default.
775      * On Linux, each node's border has to be 8MB aligned
776      */
777     mc->numa_mem_align_shift = 23;
778     mc->numa_auto_assign_ram = numa_default_auto_assign_ram;
779 
780     object_class_property_add_str(oc, "accel",
781         machine_get_accel, machine_set_accel, &error_abort);
782     object_class_property_set_description(oc, "accel",
783         "Accelerator list", &error_abort);
784 
785     object_class_property_add(oc, "kernel-irqchip", "on|off|split",
786         NULL, machine_set_kernel_irqchip,
787         NULL, NULL, &error_abort);
788     object_class_property_set_description(oc, "kernel-irqchip",
789         "Configure KVM in-kernel irqchip", &error_abort);
790 
791     object_class_property_add(oc, "kvm-shadow-mem", "int",
792         machine_get_kvm_shadow_mem, machine_set_kvm_shadow_mem,
793         NULL, NULL, &error_abort);
794     object_class_property_set_description(oc, "kvm-shadow-mem",
795         "KVM shadow MMU size", &error_abort);
796 
797     object_class_property_add_str(oc, "kernel",
798         machine_get_kernel, machine_set_kernel, &error_abort);
799     object_class_property_set_description(oc, "kernel",
800         "Linux kernel image file", &error_abort);
801 
802     object_class_property_add_str(oc, "initrd",
803         machine_get_initrd, machine_set_initrd, &error_abort);
804     object_class_property_set_description(oc, "initrd",
805         "Linux initial ramdisk file", &error_abort);
806 
807     object_class_property_add_str(oc, "append",
808         machine_get_append, machine_set_append, &error_abort);
809     object_class_property_set_description(oc, "append",
810         "Linux kernel command line", &error_abort);
811 
812     object_class_property_add_str(oc, "dtb",
813         machine_get_dtb, machine_set_dtb, &error_abort);
814     object_class_property_set_description(oc, "dtb",
815         "Linux kernel device tree file", &error_abort);
816 
817     object_class_property_add_str(oc, "dumpdtb",
818         machine_get_dumpdtb, machine_set_dumpdtb, &error_abort);
819     object_class_property_set_description(oc, "dumpdtb",
820         "Dump current dtb to a file and quit", &error_abort);
821 
822     object_class_property_add(oc, "phandle-start", "int",
823         machine_get_phandle_start, machine_set_phandle_start,
824         NULL, NULL, &error_abort);
825     object_class_property_set_description(oc, "phandle-start",
826             "The first phandle ID we may generate dynamically", &error_abort);
827 
828     object_class_property_add_str(oc, "dt-compatible",
829         machine_get_dt_compatible, machine_set_dt_compatible, &error_abort);
830     object_class_property_set_description(oc, "dt-compatible",
831         "Overrides the \"compatible\" property of the dt root node",
832         &error_abort);
833 
834     object_class_property_add_bool(oc, "dump-guest-core",
835         machine_get_dump_guest_core, machine_set_dump_guest_core, &error_abort);
836     object_class_property_set_description(oc, "dump-guest-core",
837         "Include guest memory in  a core dump", &error_abort);
838 
839     object_class_property_add_bool(oc, "mem-merge",
840         machine_get_mem_merge, machine_set_mem_merge, &error_abort);
841     object_class_property_set_description(oc, "mem-merge",
842         "Enable/disable memory merge support", &error_abort);
843 
844     object_class_property_add_bool(oc, "usb",
845         machine_get_usb, machine_set_usb, &error_abort);
846     object_class_property_set_description(oc, "usb",
847         "Set on/off to enable/disable usb", &error_abort);
848 
849     object_class_property_add_bool(oc, "graphics",
850         machine_get_graphics, machine_set_graphics, &error_abort);
851     object_class_property_set_description(oc, "graphics",
852         "Set on/off to enable/disable graphics emulation", &error_abort);
853 
854     object_class_property_add_bool(oc, "igd-passthru",
855         machine_get_igd_gfx_passthru, machine_set_igd_gfx_passthru,
856         &error_abort);
857     object_class_property_set_description(oc, "igd-passthru",
858         "Set on/off to enable/disable igd passthrou", &error_abort);
859 
860     object_class_property_add_str(oc, "firmware",
861         machine_get_firmware, machine_set_firmware,
862         &error_abort);
863     object_class_property_set_description(oc, "firmware",
864         "Firmware image", &error_abort);
865 
866     object_class_property_add_bool(oc, "suppress-vmdesc",
867         machine_get_suppress_vmdesc, machine_set_suppress_vmdesc,
868         &error_abort);
869     object_class_property_set_description(oc, "suppress-vmdesc",
870         "Set on to disable self-describing migration", &error_abort);
871 
872     object_class_property_add_bool(oc, "enforce-config-section",
873         machine_get_enforce_config_section, machine_set_enforce_config_section,
874         &error_abort);
875     object_class_property_set_description(oc, "enforce-config-section",
876         "Set on to enforce configuration section migration", &error_abort);
877 
878     object_class_property_add_str(oc, "memory-encryption",
879         machine_get_memory_encryption, machine_set_memory_encryption,
880         &error_abort);
881     object_class_property_set_description(oc, "memory-encryption",
882         "Set memory encryption object to use", &error_abort);
883 }
884 
885 static void machine_class_base_init(ObjectClass *oc, void *data)
886 {
887     if (!object_class_is_abstract(oc)) {
888         MachineClass *mc = MACHINE_CLASS(oc);
889         const char *cname = object_class_get_name(oc);
890         assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX));
891         mc->name = g_strndup(cname,
892                             strlen(cname) - strlen(TYPE_MACHINE_SUFFIX));
893         mc->compat_props = g_ptr_array_new();
894     }
895 }
896 
897 static void machine_initfn(Object *obj)
898 {
899     MachineState *ms = MACHINE(obj);
900     MachineClass *mc = MACHINE_GET_CLASS(obj);
901 
902     ms->kernel_irqchip_allowed = true;
903     ms->kernel_irqchip_split = mc->default_kernel_irqchip_split;
904     ms->kvm_shadow_mem = -1;
905     ms->dump_guest_core = true;
906     ms->mem_merge = true;
907     ms->enable_graphics = true;
908 
909     /* Register notifier when init is done for sysbus sanity checks */
910     ms->sysbus_notifier.notify = machine_init_notify;
911     qemu_add_machine_init_done_notifier(&ms->sysbus_notifier);
912 }
913 
914 static void machine_finalize(Object *obj)
915 {
916     MachineState *ms = MACHINE(obj);
917 
918     g_free(ms->accel);
919     g_free(ms->kernel_filename);
920     g_free(ms->initrd_filename);
921     g_free(ms->kernel_cmdline);
922     g_free(ms->dtb);
923     g_free(ms->dumpdtb);
924     g_free(ms->dt_compatible);
925     g_free(ms->firmware);
926     g_free(ms->device_memory);
927 }
928 
929 bool machine_usb(MachineState *machine)
930 {
931     return machine->usb;
932 }
933 
934 bool machine_kernel_irqchip_allowed(MachineState *machine)
935 {
936     return machine->kernel_irqchip_allowed;
937 }
938 
939 bool machine_kernel_irqchip_required(MachineState *machine)
940 {
941     return machine->kernel_irqchip_required;
942 }
943 
944 bool machine_kernel_irqchip_split(MachineState *machine)
945 {
946     return machine->kernel_irqchip_split;
947 }
948 
949 int machine_kvm_shadow_mem(MachineState *machine)
950 {
951     return machine->kvm_shadow_mem;
952 }
953 
954 int machine_phandle_start(MachineState *machine)
955 {
956     return machine->phandle_start;
957 }
958 
959 bool machine_dump_guest_core(MachineState *machine)
960 {
961     return machine->dump_guest_core;
962 }
963 
964 bool machine_mem_merge(MachineState *machine)
965 {
966     return machine->mem_merge;
967 }
968 
969 static char *cpu_slot_to_string(const CPUArchId *cpu)
970 {
971     GString *s = g_string_new(NULL);
972     if (cpu->props.has_socket_id) {
973         g_string_append_printf(s, "socket-id: %"PRId64, cpu->props.socket_id);
974     }
975     if (cpu->props.has_core_id) {
976         if (s->len) {
977             g_string_append_printf(s, ", ");
978         }
979         g_string_append_printf(s, "core-id: %"PRId64, cpu->props.core_id);
980     }
981     if (cpu->props.has_thread_id) {
982         if (s->len) {
983             g_string_append_printf(s, ", ");
984         }
985         g_string_append_printf(s, "thread-id: %"PRId64, cpu->props.thread_id);
986     }
987     return g_string_free(s, false);
988 }
989 
990 static void machine_numa_finish_cpu_init(MachineState *machine)
991 {
992     int i;
993     bool default_mapping;
994     GString *s = g_string_new(NULL);
995     MachineClass *mc = MACHINE_GET_CLASS(machine);
996     const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(machine);
997 
998     assert(nb_numa_nodes);
999     for (i = 0; i < possible_cpus->len; i++) {
1000         if (possible_cpus->cpus[i].props.has_node_id) {
1001             break;
1002         }
1003     }
1004     default_mapping = (i == possible_cpus->len);
1005 
1006     for (i = 0; i < possible_cpus->len; i++) {
1007         const CPUArchId *cpu_slot = &possible_cpus->cpus[i];
1008 
1009         if (!cpu_slot->props.has_node_id) {
1010             /* fetch default mapping from board and enable it */
1011             CpuInstanceProperties props = cpu_slot->props;
1012 
1013             props.node_id = mc->get_default_cpu_node_id(machine, i);
1014             if (!default_mapping) {
1015                 /* record slots with not set mapping,
1016                  * TODO: make it hard error in future */
1017                 char *cpu_str = cpu_slot_to_string(cpu_slot);
1018                 g_string_append_printf(s, "%sCPU %d [%s]",
1019                                        s->len ? ", " : "", i, cpu_str);
1020                 g_free(cpu_str);
1021 
1022                 /* non mapped cpus used to fallback to node 0 */
1023                 props.node_id = 0;
1024             }
1025 
1026             props.has_node_id = true;
1027             machine_set_cpu_numa_node(machine, &props, &error_fatal);
1028         }
1029     }
1030     if (s->len && !qtest_enabled()) {
1031         warn_report("CPU(s) not present in any NUMA nodes: %s",
1032                     s->str);
1033         warn_report("All CPU(s) up to maxcpus should be described "
1034                     "in NUMA config, ability to start up with partial NUMA "
1035                     "mappings is obsoleted and will be removed in future");
1036     }
1037     g_string_free(s, true);
1038 }
1039 
1040 void machine_run_board_init(MachineState *machine)
1041 {
1042     MachineClass *machine_class = MACHINE_GET_CLASS(machine);
1043 
1044     numa_complete_configuration(machine);
1045     if (nb_numa_nodes) {
1046         machine_numa_finish_cpu_init(machine);
1047     }
1048 
1049     /* If the machine supports the valid_cpu_types check and the user
1050      * specified a CPU with -cpu check here that the user CPU is supported.
1051      */
1052     if (machine_class->valid_cpu_types && machine->cpu_type) {
1053         ObjectClass *class = object_class_by_name(machine->cpu_type);
1054         int i;
1055 
1056         for (i = 0; machine_class->valid_cpu_types[i]; i++) {
1057             if (object_class_dynamic_cast(class,
1058                                           machine_class->valid_cpu_types[i])) {
1059                 /* The user specificed CPU is in the valid field, we are
1060                  * good to go.
1061                  */
1062                 break;
1063             }
1064         }
1065 
1066         if (!machine_class->valid_cpu_types[i]) {
1067             /* The user specified CPU is not valid */
1068             error_report("Invalid CPU type: %s", machine->cpu_type);
1069             error_printf("The valid types are: %s",
1070                          machine_class->valid_cpu_types[0]);
1071             for (i = 1; machine_class->valid_cpu_types[i]; i++) {
1072                 error_printf(", %s", machine_class->valid_cpu_types[i]);
1073             }
1074             error_printf("\n");
1075 
1076             exit(1);
1077         }
1078     }
1079 
1080     machine_class->init(machine);
1081 }
1082 
1083 static const TypeInfo machine_info = {
1084     .name = TYPE_MACHINE,
1085     .parent = TYPE_OBJECT,
1086     .abstract = true,
1087     .class_size = sizeof(MachineClass),
1088     .class_init    = machine_class_init,
1089     .class_base_init = machine_class_base_init,
1090     .instance_size = sizeof(MachineState),
1091     .instance_init = machine_initfn,
1092     .instance_finalize = machine_finalize,
1093 };
1094 
1095 static void machine_register_types(void)
1096 {
1097     type_register_static(&machine_info);
1098 }
1099 
1100 type_init(machine_register_types)
1101