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