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