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