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