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