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