xref: /openbmc/qemu/hw/core/machine.c (revision 5a995064dbaf64c0bbc45ce8745ab4e49c434b37)
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 static char *machine_get_accel(Object *obj, Error **errp)
197 {
198     MachineState *ms = MACHINE(obj);
199 
200     return g_strdup(ms->accel);
201 }
202 
203 static void machine_set_accel(Object *obj, const char *value, Error **errp)
204 {
205     MachineState *ms = MACHINE(obj);
206 
207     g_free(ms->accel);
208     ms->accel = g_strdup(value);
209 }
210 
211 static void machine_set_kernel_irqchip(Object *obj, Visitor *v,
212                                        const char *name, void *opaque,
213                                        Error **errp)
214 {
215     Error *err = NULL;
216     MachineState *ms = MACHINE(obj);
217     OnOffSplit mode;
218 
219     visit_type_OnOffSplit(v, name, &mode, &err);
220     if (err) {
221         error_propagate(errp, err);
222         return;
223     } else {
224         switch (mode) {
225         case ON_OFF_SPLIT_ON:
226             ms->kernel_irqchip_allowed = true;
227             ms->kernel_irqchip_required = true;
228             ms->kernel_irqchip_split = false;
229             break;
230         case ON_OFF_SPLIT_OFF:
231             ms->kernel_irqchip_allowed = false;
232             ms->kernel_irqchip_required = false;
233             ms->kernel_irqchip_split = false;
234             break;
235         case ON_OFF_SPLIT_SPLIT:
236             ms->kernel_irqchip_allowed = true;
237             ms->kernel_irqchip_required = true;
238             ms->kernel_irqchip_split = true;
239             break;
240         default:
241             /* The value was checked in visit_type_OnOffSplit() above. If
242              * we get here, then something is wrong in QEMU.
243              */
244             abort();
245         }
246     }
247 }
248 
249 static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v,
250                                        const char *name, void *opaque,
251                                        Error **errp)
252 {
253     MachineState *ms = MACHINE(obj);
254     int64_t value = ms->kvm_shadow_mem;
255 
256     visit_type_int(v, name, &value, errp);
257 }
258 
259 static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v,
260                                        const char *name, void *opaque,
261                                        Error **errp)
262 {
263     MachineState *ms = MACHINE(obj);
264     Error *error = NULL;
265     int64_t value;
266 
267     visit_type_int(v, name, &value, &error);
268     if (error) {
269         error_propagate(errp, error);
270         return;
271     }
272 
273     ms->kvm_shadow_mem = value;
274 }
275 
276 static char *machine_get_kernel(Object *obj, Error **errp)
277 {
278     MachineState *ms = MACHINE(obj);
279 
280     return g_strdup(ms->kernel_filename);
281 }
282 
283 static void machine_set_kernel(Object *obj, const char *value, Error **errp)
284 {
285     MachineState *ms = MACHINE(obj);
286 
287     g_free(ms->kernel_filename);
288     ms->kernel_filename = g_strdup(value);
289 }
290 
291 static char *machine_get_initrd(Object *obj, Error **errp)
292 {
293     MachineState *ms = MACHINE(obj);
294 
295     return g_strdup(ms->initrd_filename);
296 }
297 
298 static void machine_set_initrd(Object *obj, const char *value, Error **errp)
299 {
300     MachineState *ms = MACHINE(obj);
301 
302     g_free(ms->initrd_filename);
303     ms->initrd_filename = g_strdup(value);
304 }
305 
306 static char *machine_get_append(Object *obj, Error **errp)
307 {
308     MachineState *ms = MACHINE(obj);
309 
310     return g_strdup(ms->kernel_cmdline);
311 }
312 
313 static void machine_set_append(Object *obj, const char *value, Error **errp)
314 {
315     MachineState *ms = MACHINE(obj);
316 
317     g_free(ms->kernel_cmdline);
318     ms->kernel_cmdline = g_strdup(value);
319 }
320 
321 static char *machine_get_dtb(Object *obj, Error **errp)
322 {
323     MachineState *ms = MACHINE(obj);
324 
325     return g_strdup(ms->dtb);
326 }
327 
328 static void machine_set_dtb(Object *obj, const char *value, Error **errp)
329 {
330     MachineState *ms = MACHINE(obj);
331 
332     g_free(ms->dtb);
333     ms->dtb = g_strdup(value);
334 }
335 
336 static char *machine_get_dumpdtb(Object *obj, Error **errp)
337 {
338     MachineState *ms = MACHINE(obj);
339 
340     return g_strdup(ms->dumpdtb);
341 }
342 
343 static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp)
344 {
345     MachineState *ms = MACHINE(obj);
346 
347     g_free(ms->dumpdtb);
348     ms->dumpdtb = g_strdup(value);
349 }
350 
351 static void machine_get_phandle_start(Object *obj, Visitor *v,
352                                       const char *name, void *opaque,
353                                       Error **errp)
354 {
355     MachineState *ms = MACHINE(obj);
356     int64_t value = ms->phandle_start;
357 
358     visit_type_int(v, name, &value, errp);
359 }
360 
361 static void machine_set_phandle_start(Object *obj, Visitor *v,
362                                       const char *name, void *opaque,
363                                       Error **errp)
364 {
365     MachineState *ms = MACHINE(obj);
366     Error *error = NULL;
367     int64_t value;
368 
369     visit_type_int(v, name, &value, &error);
370     if (error) {
371         error_propagate(errp, error);
372         return;
373     }
374 
375     ms->phandle_start = value;
376 }
377 
378 static char *machine_get_dt_compatible(Object *obj, Error **errp)
379 {
380     MachineState *ms = MACHINE(obj);
381 
382     return g_strdup(ms->dt_compatible);
383 }
384 
385 static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp)
386 {
387     MachineState *ms = MACHINE(obj);
388 
389     g_free(ms->dt_compatible);
390     ms->dt_compatible = g_strdup(value);
391 }
392 
393 static bool machine_get_dump_guest_core(Object *obj, Error **errp)
394 {
395     MachineState *ms = MACHINE(obj);
396 
397     return ms->dump_guest_core;
398 }
399 
400 static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp)
401 {
402     MachineState *ms = MACHINE(obj);
403 
404     ms->dump_guest_core = value;
405 }
406 
407 static bool machine_get_mem_merge(Object *obj, Error **errp)
408 {
409     MachineState *ms = MACHINE(obj);
410 
411     return ms->mem_merge;
412 }
413 
414 static void machine_set_mem_merge(Object *obj, bool value, Error **errp)
415 {
416     MachineState *ms = MACHINE(obj);
417 
418     ms->mem_merge = value;
419 }
420 
421 static bool machine_get_usb(Object *obj, Error **errp)
422 {
423     MachineState *ms = MACHINE(obj);
424 
425     return ms->usb;
426 }
427 
428 static void machine_set_usb(Object *obj, bool value, Error **errp)
429 {
430     MachineState *ms = MACHINE(obj);
431 
432     ms->usb = value;
433     ms->usb_disabled = !value;
434 }
435 
436 static bool machine_get_graphics(Object *obj, Error **errp)
437 {
438     MachineState *ms = MACHINE(obj);
439 
440     return ms->enable_graphics;
441 }
442 
443 static void machine_set_graphics(Object *obj, bool value, Error **errp)
444 {
445     MachineState *ms = MACHINE(obj);
446 
447     ms->enable_graphics = value;
448 }
449 
450 static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp)
451 {
452     MachineState *ms = MACHINE(obj);
453 
454     return ms->igd_gfx_passthru;
455 }
456 
457 static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
458 {
459     MachineState *ms = MACHINE(obj);
460 
461     ms->igd_gfx_passthru = value;
462 }
463 
464 static char *machine_get_firmware(Object *obj, Error **errp)
465 {
466     MachineState *ms = MACHINE(obj);
467 
468     return g_strdup(ms->firmware);
469 }
470 
471 static void machine_set_firmware(Object *obj, const char *value, Error **errp)
472 {
473     MachineState *ms = MACHINE(obj);
474 
475     g_free(ms->firmware);
476     ms->firmware = g_strdup(value);
477 }
478 
479 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
480 {
481     MachineState *ms = MACHINE(obj);
482 
483     ms->suppress_vmdesc = value;
484 }
485 
486 static bool machine_get_suppress_vmdesc(Object *obj, Error **errp)
487 {
488     MachineState *ms = MACHINE(obj);
489 
490     return ms->suppress_vmdesc;
491 }
492 
493 static void machine_set_enforce_config_section(Object *obj, bool value,
494                                              Error **errp)
495 {
496     MachineState *ms = MACHINE(obj);
497 
498     warn_report("enforce-config-section is deprecated, please use "
499                 "-global migration.send-configuration=on|off instead");
500 
501     ms->enforce_config_section = value;
502 }
503 
504 static bool machine_get_enforce_config_section(Object *obj, Error **errp)
505 {
506     MachineState *ms = MACHINE(obj);
507 
508     return ms->enforce_config_section;
509 }
510 
511 static char *machine_get_memory_encryption(Object *obj, Error **errp)
512 {
513     MachineState *ms = MACHINE(obj);
514 
515     return g_strdup(ms->memory_encryption);
516 }
517 
518 static void machine_set_memory_encryption(Object *obj, const char *value,
519                                         Error **errp)
520 {
521     MachineState *ms = MACHINE(obj);
522 
523     g_free(ms->memory_encryption);
524     ms->memory_encryption = g_strdup(value);
525 }
526 
527 void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type)
528 {
529     strList *item = g_new0(strList, 1);
530 
531     item->value = g_strdup(type);
532     item->next = mc->allowed_dynamic_sysbus_devices;
533     mc->allowed_dynamic_sysbus_devices = item;
534 }
535 
536 static void validate_sysbus_device(SysBusDevice *sbdev, void *opaque)
537 {
538     MachineState *machine = opaque;
539     MachineClass *mc = MACHINE_GET_CLASS(machine);
540     bool allowed = false;
541     strList *wl;
542 
543     for (wl = mc->allowed_dynamic_sysbus_devices;
544          !allowed && wl;
545          wl = wl->next) {
546         allowed |= !!object_dynamic_cast(OBJECT(sbdev), wl->value);
547     }
548 
549     if (!allowed) {
550         error_report("Option '-device %s' cannot be handled by this machine",
551                      object_class_get_name(object_get_class(OBJECT(sbdev))));
552         exit(1);
553     }
554 }
555 
556 static void machine_init_notify(Notifier *notifier, void *data)
557 {
558     MachineState *machine = MACHINE(qdev_get_machine());
559 
560     /*
561      * Loop through all dynamically created sysbus devices and check if they are
562      * all allowed.  If a device is not allowed, error out.
563      */
564     foreach_dynamic_sysbus_device(validate_sysbus_device, machine);
565 }
566 
567 HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine)
568 {
569     int i;
570     HotpluggableCPUList *head = NULL;
571     MachineClass *mc = MACHINE_GET_CLASS(machine);
572 
573     /* force board to initialize possible_cpus if it hasn't been done yet */
574     mc->possible_cpu_arch_ids(machine);
575 
576     for (i = 0; i < machine->possible_cpus->len; i++) {
577         Object *cpu;
578         HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1);
579         HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1);
580 
581         cpu_item->type = g_strdup(machine->possible_cpus->cpus[i].type);
582         cpu_item->vcpus_count = machine->possible_cpus->cpus[i].vcpus_count;
583         cpu_item->props = g_memdup(&machine->possible_cpus->cpus[i].props,
584                                    sizeof(*cpu_item->props));
585 
586         cpu = machine->possible_cpus->cpus[i].cpu;
587         if (cpu) {
588             cpu_item->has_qom_path = true;
589             cpu_item->qom_path = object_get_canonical_path(cpu);
590         }
591         list_item->value = cpu_item;
592         list_item->next = head;
593         head = list_item;
594     }
595     return head;
596 }
597 
598 /**
599  * machine_set_cpu_numa_node:
600  * @machine: machine object to modify
601  * @props: specifies which cpu objects to assign to
602  *         numa node specified by @props.node_id
603  * @errp: if an error occurs, a pointer to an area to store the error
604  *
605  * Associate NUMA node specified by @props.node_id with cpu slots that
606  * match socket/core/thread-ids specified by @props. It's recommended to use
607  * query-hotpluggable-cpus.props values to specify affected cpu slots,
608  * which would lead to exact 1:1 mapping of cpu slots to NUMA node.
609  *
610  * However for CLI convenience it's possible to pass in subset of properties,
611  * which would affect all cpu slots that match it.
612  * Ex for pc machine:
613  *    -smp 4,cores=2,sockets=2 -numa node,nodeid=0 -numa node,nodeid=1 \
614  *    -numa cpu,node-id=0,socket_id=0 \
615  *    -numa cpu,node-id=1,socket_id=1
616  * will assign all child cores of socket 0 to node 0 and
617  * of socket 1 to node 1.
618  *
619  * On attempt of reassigning (already assigned) cpu slot to another NUMA node,
620  * return error.
621  * Empty subset is disallowed and function will return with error in this case.
622  */
623 void machine_set_cpu_numa_node(MachineState *machine,
624                                const CpuInstanceProperties *props, Error **errp)
625 {
626     MachineClass *mc = MACHINE_GET_CLASS(machine);
627     bool match = false;
628     int i;
629 
630     if (!mc->possible_cpu_arch_ids) {
631         error_setg(errp, "mapping of CPUs to NUMA node is not supported");
632         return;
633     }
634 
635     /* disabling node mapping is not supported, forbid it */
636     assert(props->has_node_id);
637 
638     /* force board to initialize possible_cpus if it hasn't been done yet */
639     mc->possible_cpu_arch_ids(machine);
640 
641     for (i = 0; i < machine->possible_cpus->len; i++) {
642         CPUArchId *slot = &machine->possible_cpus->cpus[i];
643 
644         /* reject unsupported by board properties */
645         if (props->has_thread_id && !slot->props.has_thread_id) {
646             error_setg(errp, "thread-id is not supported");
647             return;
648         }
649 
650         if (props->has_core_id && !slot->props.has_core_id) {
651             error_setg(errp, "core-id is not supported");
652             return;
653         }
654 
655         if (props->has_socket_id && !slot->props.has_socket_id) {
656             error_setg(errp, "socket-id is not supported");
657             return;
658         }
659 
660         /* skip slots with explicit mismatch */
661         if (props->has_thread_id && props->thread_id != slot->props.thread_id) {
662                 continue;
663         }
664 
665         if (props->has_core_id && props->core_id != slot->props.core_id) {
666                 continue;
667         }
668 
669         if (props->has_socket_id && props->socket_id != slot->props.socket_id) {
670                 continue;
671         }
672 
673         /* reject assignment if slot is already assigned, for compatibility
674          * of legacy cpu_index mapping with SPAPR core based mapping do not
675          * error out if cpu thread and matched core have the same node-id */
676         if (slot->props.has_node_id &&
677             slot->props.node_id != props->node_id) {
678             error_setg(errp, "CPU is already assigned to node-id: %" PRId64,
679                        slot->props.node_id);
680             return;
681         }
682 
683         /* assign slot to node as it's matched '-numa cpu' key */
684         match = true;
685         slot->props.node_id = props->node_id;
686         slot->props.has_node_id = props->has_node_id;
687     }
688 
689     if (!match) {
690         error_setg(errp, "no match found");
691     }
692 }
693 
694 static void machine_class_init(ObjectClass *oc, void *data)
695 {
696     MachineClass *mc = MACHINE_CLASS(oc);
697 
698     /* Default 128 MB as guest ram size */
699     mc->default_ram_size = 128 * MiB;
700     mc->rom_file_has_mr = true;
701 
702     /* numa node memory size aligned on 8MB by default.
703      * On Linux, each node's border has to be 8MB aligned
704      */
705     mc->numa_mem_align_shift = 23;
706     mc->numa_auto_assign_ram = numa_default_auto_assign_ram;
707 
708     object_class_property_add_str(oc, "accel",
709         machine_get_accel, machine_set_accel, &error_abort);
710     object_class_property_set_description(oc, "accel",
711         "Accelerator list", &error_abort);
712 
713     object_class_property_add(oc, "kernel-irqchip", "on|off|split",
714         NULL, machine_set_kernel_irqchip,
715         NULL, NULL, &error_abort);
716     object_class_property_set_description(oc, "kernel-irqchip",
717         "Configure KVM in-kernel irqchip", &error_abort);
718 
719     object_class_property_add(oc, "kvm-shadow-mem", "int",
720         machine_get_kvm_shadow_mem, machine_set_kvm_shadow_mem,
721         NULL, NULL, &error_abort);
722     object_class_property_set_description(oc, "kvm-shadow-mem",
723         "KVM shadow MMU size", &error_abort);
724 
725     object_class_property_add_str(oc, "kernel",
726         machine_get_kernel, machine_set_kernel, &error_abort);
727     object_class_property_set_description(oc, "kernel",
728         "Linux kernel image file", &error_abort);
729 
730     object_class_property_add_str(oc, "initrd",
731         machine_get_initrd, machine_set_initrd, &error_abort);
732     object_class_property_set_description(oc, "initrd",
733         "Linux initial ramdisk file", &error_abort);
734 
735     object_class_property_add_str(oc, "append",
736         machine_get_append, machine_set_append, &error_abort);
737     object_class_property_set_description(oc, "append",
738         "Linux kernel command line", &error_abort);
739 
740     object_class_property_add_str(oc, "dtb",
741         machine_get_dtb, machine_set_dtb, &error_abort);
742     object_class_property_set_description(oc, "dtb",
743         "Linux kernel device tree file", &error_abort);
744 
745     object_class_property_add_str(oc, "dumpdtb",
746         machine_get_dumpdtb, machine_set_dumpdtb, &error_abort);
747     object_class_property_set_description(oc, "dumpdtb",
748         "Dump current dtb to a file and quit", &error_abort);
749 
750     object_class_property_add(oc, "phandle-start", "int",
751         machine_get_phandle_start, machine_set_phandle_start,
752         NULL, NULL, &error_abort);
753     object_class_property_set_description(oc, "phandle-start",
754             "The first phandle ID we may generate dynamically", &error_abort);
755 
756     object_class_property_add_str(oc, "dt-compatible",
757         machine_get_dt_compatible, machine_set_dt_compatible, &error_abort);
758     object_class_property_set_description(oc, "dt-compatible",
759         "Overrides the \"compatible\" property of the dt root node",
760         &error_abort);
761 
762     object_class_property_add_bool(oc, "dump-guest-core",
763         machine_get_dump_guest_core, machine_set_dump_guest_core, &error_abort);
764     object_class_property_set_description(oc, "dump-guest-core",
765         "Include guest memory in  a core dump", &error_abort);
766 
767     object_class_property_add_bool(oc, "mem-merge",
768         machine_get_mem_merge, machine_set_mem_merge, &error_abort);
769     object_class_property_set_description(oc, "mem-merge",
770         "Enable/disable memory merge support", &error_abort);
771 
772     object_class_property_add_bool(oc, "usb",
773         machine_get_usb, machine_set_usb, &error_abort);
774     object_class_property_set_description(oc, "usb",
775         "Set on/off to enable/disable usb", &error_abort);
776 
777     object_class_property_add_bool(oc, "graphics",
778         machine_get_graphics, machine_set_graphics, &error_abort);
779     object_class_property_set_description(oc, "graphics",
780         "Set on/off to enable/disable graphics emulation", &error_abort);
781 
782     object_class_property_add_bool(oc, "igd-passthru",
783         machine_get_igd_gfx_passthru, machine_set_igd_gfx_passthru,
784         &error_abort);
785     object_class_property_set_description(oc, "igd-passthru",
786         "Set on/off to enable/disable igd passthrou", &error_abort);
787 
788     object_class_property_add_str(oc, "firmware",
789         machine_get_firmware, machine_set_firmware,
790         &error_abort);
791     object_class_property_set_description(oc, "firmware",
792         "Firmware image", &error_abort);
793 
794     object_class_property_add_bool(oc, "suppress-vmdesc",
795         machine_get_suppress_vmdesc, machine_set_suppress_vmdesc,
796         &error_abort);
797     object_class_property_set_description(oc, "suppress-vmdesc",
798         "Set on to disable self-describing migration", &error_abort);
799 
800     object_class_property_add_bool(oc, "enforce-config-section",
801         machine_get_enforce_config_section, machine_set_enforce_config_section,
802         &error_abort);
803     object_class_property_set_description(oc, "enforce-config-section",
804         "Set on to enforce configuration section migration", &error_abort);
805 
806     object_class_property_add_str(oc, "memory-encryption",
807         machine_get_memory_encryption, machine_set_memory_encryption,
808         &error_abort);
809     object_class_property_set_description(oc, "memory-encryption",
810         "Set memory encryption object to use", &error_abort);
811 }
812 
813 static void machine_class_base_init(ObjectClass *oc, void *data)
814 {
815     if (!object_class_is_abstract(oc)) {
816         MachineClass *mc = MACHINE_CLASS(oc);
817         const char *cname = object_class_get_name(oc);
818         assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX));
819         mc->name = g_strndup(cname,
820                             strlen(cname) - strlen(TYPE_MACHINE_SUFFIX));
821         mc->compat_props = g_ptr_array_new();
822     }
823 }
824 
825 static void machine_initfn(Object *obj)
826 {
827     MachineState *ms = MACHINE(obj);
828     MachineClass *mc = MACHINE_GET_CLASS(obj);
829 
830     ms->kernel_irqchip_allowed = true;
831     ms->kernel_irqchip_split = mc->default_kernel_irqchip_split;
832     ms->kvm_shadow_mem = -1;
833     ms->dump_guest_core = true;
834     ms->mem_merge = true;
835     ms->enable_graphics = true;
836 
837     /* Register notifier when init is done for sysbus sanity checks */
838     ms->sysbus_notifier.notify = machine_init_notify;
839     qemu_add_machine_init_done_notifier(&ms->sysbus_notifier);
840 }
841 
842 static void machine_finalize(Object *obj)
843 {
844     MachineState *ms = MACHINE(obj);
845 
846     g_free(ms->accel);
847     g_free(ms->kernel_filename);
848     g_free(ms->initrd_filename);
849     g_free(ms->kernel_cmdline);
850     g_free(ms->dtb);
851     g_free(ms->dumpdtb);
852     g_free(ms->dt_compatible);
853     g_free(ms->firmware);
854     g_free(ms->device_memory);
855 }
856 
857 bool machine_usb(MachineState *machine)
858 {
859     return machine->usb;
860 }
861 
862 bool machine_kernel_irqchip_allowed(MachineState *machine)
863 {
864     return machine->kernel_irqchip_allowed;
865 }
866 
867 bool machine_kernel_irqchip_required(MachineState *machine)
868 {
869     return machine->kernel_irqchip_required;
870 }
871 
872 bool machine_kernel_irqchip_split(MachineState *machine)
873 {
874     return machine->kernel_irqchip_split;
875 }
876 
877 int machine_kvm_shadow_mem(MachineState *machine)
878 {
879     return machine->kvm_shadow_mem;
880 }
881 
882 int machine_phandle_start(MachineState *machine)
883 {
884     return machine->phandle_start;
885 }
886 
887 bool machine_dump_guest_core(MachineState *machine)
888 {
889     return machine->dump_guest_core;
890 }
891 
892 bool machine_mem_merge(MachineState *machine)
893 {
894     return machine->mem_merge;
895 }
896 
897 static char *cpu_slot_to_string(const CPUArchId *cpu)
898 {
899     GString *s = g_string_new(NULL);
900     if (cpu->props.has_socket_id) {
901         g_string_append_printf(s, "socket-id: %"PRId64, cpu->props.socket_id);
902     }
903     if (cpu->props.has_core_id) {
904         if (s->len) {
905             g_string_append_printf(s, ", ");
906         }
907         g_string_append_printf(s, "core-id: %"PRId64, cpu->props.core_id);
908     }
909     if (cpu->props.has_thread_id) {
910         if (s->len) {
911             g_string_append_printf(s, ", ");
912         }
913         g_string_append_printf(s, "thread-id: %"PRId64, cpu->props.thread_id);
914     }
915     return g_string_free(s, false);
916 }
917 
918 static void machine_numa_finish_cpu_init(MachineState *machine)
919 {
920     int i;
921     bool default_mapping;
922     GString *s = g_string_new(NULL);
923     MachineClass *mc = MACHINE_GET_CLASS(machine);
924     const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(machine);
925 
926     assert(nb_numa_nodes);
927     for (i = 0; i < possible_cpus->len; i++) {
928         if (possible_cpus->cpus[i].props.has_node_id) {
929             break;
930         }
931     }
932     default_mapping = (i == possible_cpus->len);
933 
934     for (i = 0; i < possible_cpus->len; i++) {
935         const CPUArchId *cpu_slot = &possible_cpus->cpus[i];
936 
937         if (!cpu_slot->props.has_node_id) {
938             /* fetch default mapping from board and enable it */
939             CpuInstanceProperties props = cpu_slot->props;
940 
941             props.node_id = mc->get_default_cpu_node_id(machine, i);
942             if (!default_mapping) {
943                 /* record slots with not set mapping,
944                  * TODO: make it hard error in future */
945                 char *cpu_str = cpu_slot_to_string(cpu_slot);
946                 g_string_append_printf(s, "%sCPU %d [%s]",
947                                        s->len ? ", " : "", i, cpu_str);
948                 g_free(cpu_str);
949 
950                 /* non mapped cpus used to fallback to node 0 */
951                 props.node_id = 0;
952             }
953 
954             props.has_node_id = true;
955             machine_set_cpu_numa_node(machine, &props, &error_fatal);
956         }
957     }
958     if (s->len && !qtest_enabled()) {
959         warn_report("CPU(s) not present in any NUMA nodes: %s",
960                     s->str);
961         warn_report("All CPU(s) up to maxcpus should be described "
962                     "in NUMA config, ability to start up with partial NUMA "
963                     "mappings is obsoleted and will be removed in future");
964     }
965     g_string_free(s, true);
966 }
967 
968 void machine_run_board_init(MachineState *machine)
969 {
970     MachineClass *machine_class = MACHINE_GET_CLASS(machine);
971 
972     numa_complete_configuration(machine);
973     if (nb_numa_nodes) {
974         machine_numa_finish_cpu_init(machine);
975     }
976 
977     /* If the machine supports the valid_cpu_types check and the user
978      * specified a CPU with -cpu check here that the user CPU is supported.
979      */
980     if (machine_class->valid_cpu_types && machine->cpu_type) {
981         ObjectClass *class = object_class_by_name(machine->cpu_type);
982         int i;
983 
984         for (i = 0; machine_class->valid_cpu_types[i]; i++) {
985             if (object_class_dynamic_cast(class,
986                                           machine_class->valid_cpu_types[i])) {
987                 /* The user specificed CPU is in the valid field, we are
988                  * good to go.
989                  */
990                 break;
991             }
992         }
993 
994         if (!machine_class->valid_cpu_types[i]) {
995             /* The user specified CPU is not valid */
996             error_report("Invalid CPU type: %s", machine->cpu_type);
997             error_printf("The valid types are: %s",
998                          machine_class->valid_cpu_types[0]);
999             for (i = 1; machine_class->valid_cpu_types[i]; i++) {
1000                 error_printf(", %s", machine_class->valid_cpu_types[i]);
1001             }
1002             error_printf("\n");
1003 
1004             exit(1);
1005         }
1006     }
1007 
1008     machine_class->init(machine);
1009 }
1010 
1011 static const TypeInfo machine_info = {
1012     .name = TYPE_MACHINE,
1013     .parent = TYPE_OBJECT,
1014     .abstract = true,
1015     .class_size = sizeof(MachineClass),
1016     .class_init    = machine_class_init,
1017     .class_base_init = machine_class_base_init,
1018     .instance_size = sizeof(MachineState),
1019     .instance_init = machine_initfn,
1020     .instance_finalize = machine_finalize,
1021 };
1022 
1023 static void machine_register_types(void)
1024 {
1025     type_register_static(&machine_info);
1026 }
1027 
1028 type_init(machine_register_types)
1029