4 * Copyright (C) 2014 Red Hat Inc
7 * Marcel Apfelbaum <marcel.a@redhat.com>
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.
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"
26 GlobalProperty hw_compat_3_1
[] = {
28 .driver
= "pcie-root-port",
29 .property
= "x-speed",
32 .driver
= "pcie-root-port",
33 .property
= "x-width",
37 const size_t hw_compat_3_1_len
= G_N_ELEMENTS(hw_compat_3_1
);
39 GlobalProperty hw_compat_3_0
[] = {};
40 const size_t hw_compat_3_0_len
= G_N_ELEMENTS(hw_compat_3_0
);
42 GlobalProperty hw_compat_2_12
[] = {
44 .driver
= "migration",
45 .property
= "decompress-error-check",
48 .driver
= "hda-audio",
49 .property
= "use-timer",
52 .driver
= "cirrus-vga",
53 .property
= "global-vmstate",
57 .property
= "global-vmstate",
60 .driver
= "vmware-svga",
61 .property
= "global-vmstate",
65 .property
= "global-vmstate",
69 const size_t hw_compat_2_12_len
= G_N_ELEMENTS(hw_compat_2_12
);
71 GlobalProperty hw_compat_2_11
[] = {
74 .property
= "hpet-offset-saved",
77 .driver
= "virtio-blk-pci",
78 .property
= "vectors",
81 .driver
= "vhost-user-blk-pci",
82 .property
= "vectors",
86 .property
= "migrate_tso_props",
90 const size_t hw_compat_2_11_len
= G_N_ELEMENTS(hw_compat_2_11
);
92 GlobalProperty hw_compat_2_10
[] = {
94 .driver
= "virtio-mouse-device",
95 .property
= "wheel-axis",
98 .driver
= "virtio-tablet-device",
99 .property
= "wheel-axis",
103 const size_t hw_compat_2_10_len
= G_N_ELEMENTS(hw_compat_2_10
);
105 GlobalProperty hw_compat_2_9
[] = {
107 .driver
= "pci-bridge",
111 .driver
= "intel-iommu",
115 .driver
= "virtio-net-device",
116 .property
= "x-mtu-bypass-backend",
119 .driver
= "pcie-root-port",
120 .property
= "x-migrate-msix",
124 const size_t hw_compat_2_9_len
= G_N_ELEMENTS(hw_compat_2_9
);
126 GlobalProperty hw_compat_2_8
[] = {
128 .driver
= "fw_cfg_mem",
129 .property
= "x-file-slots",
130 .value
= stringify(0x10),
132 .driver
= "fw_cfg_io",
133 .property
= "x-file-slots",
134 .value
= stringify(0x10),
136 .driver
= "pflash_cfi01",
137 .property
= "old-multiple-chip-handling",
140 .driver
= "pci-bridge",
144 .driver
= TYPE_PCI_DEVICE
,
145 .property
= "x-pcie-extcap-init",
148 .driver
= "virtio-pci",
149 .property
= "x-pcie-deverr-init",
152 .driver
= "virtio-pci",
153 .property
= "x-pcie-lnkctl-init",
156 .driver
= "virtio-pci",
157 .property
= "x-pcie-pm-init",
160 .driver
= "cirrus-vga",
161 .property
= "vgamem_mb",
164 .driver
= "isa-cirrus-vga",
165 .property
= "vgamem_mb",
169 const size_t hw_compat_2_8_len
= G_N_ELEMENTS(hw_compat_2_8
);
171 GlobalProperty hw_compat_2_7
[] = {
173 .driver
= "virtio-pci",
174 .property
= "page-per-vq",
177 .driver
= "virtio-serial-device",
178 .property
= "emergency-write",
182 .property
= "version",
185 .driver
= "intel-iommu",
186 .property
= "x-buggy-eim",
189 .driver
= "virtio-pci",
190 .property
= "x-ignore-backend-features",
194 const size_t hw_compat_2_7_len
= G_N_ELEMENTS(hw_compat_2_7
);
196 GlobalProperty hw_compat_2_6
[] = {
198 .driver
= "virtio-mmio",
199 .property
= "format_transport_address",
202 .driver
= "virtio-pci",
203 .property
= "disable-modern",
206 .driver
= "virtio-pci",
207 .property
= "disable-legacy",
211 const size_t hw_compat_2_6_len
= G_N_ELEMENTS(hw_compat_2_6
);
213 GlobalProperty hw_compat_2_5
[] = {
216 .property
= "fallback",
220 .property
= "x-old-pci-configuration",
224 .property
= "x-disable-pcie",
229 .property
= "x-old-msi-offsets",
233 .property
= "x-disable-pcie",
237 const size_t hw_compat_2_5_len
= G_N_ELEMENTS(hw_compat_2_5
);
239 GlobalProperty hw_compat_2_4
[] = {
241 .driver
= "virtio-blk-device",
246 .property
= "extra_mac_registers",
249 .driver
= "virtio-pci",
250 .property
= "x-disable-pcie",
253 .driver
= "virtio-pci",
254 .property
= "migrate-extra",
257 .driver
= "fw_cfg_mem",
258 .property
= "dma_enabled",
261 .driver
= "fw_cfg_io",
262 .property
= "dma_enabled",
266 const size_t hw_compat_2_4_len
= G_N_ELEMENTS(hw_compat_2_4
);
268 GlobalProperty hw_compat_2_3
[] = {
270 .driver
= "virtio-blk-pci",
271 .property
= "any_layout",
274 .driver
= "virtio-balloon-pci",
275 .property
= "any_layout",
278 .driver
= "virtio-serial-pci",
279 .property
= "any_layout",
282 .driver
= "virtio-9p-pci",
283 .property
= "any_layout",
286 .driver
= "virtio-rng-pci",
287 .property
= "any_layout",
290 .driver
= TYPE_PCI_DEVICE
,
291 .property
= "x-pcie-lnksta-dllla",
294 .driver
= "migration",
295 .property
= "send-configuration",
298 .driver
= "migration",
299 .property
= "send-section-footer",
302 .driver
= "migration",
303 .property
= "store-global-state",
307 const size_t hw_compat_2_3_len
= G_N_ELEMENTS(hw_compat_2_3
);
309 GlobalProperty hw_compat_2_2
[] = {};
310 const size_t hw_compat_2_2_len
= G_N_ELEMENTS(hw_compat_2_2
);
312 static char *machine_get_accel(Object
*obj
, Error
**errp
)
314 MachineState
*ms
= MACHINE(obj
);
316 return g_strdup(ms
->accel
);
319 static void machine_set_accel(Object
*obj
, const char *value
, Error
**errp
)
321 MachineState
*ms
= MACHINE(obj
);
324 ms
->accel
= g_strdup(value
);
327 static void machine_set_kernel_irqchip(Object
*obj
, Visitor
*v
,
328 const char *name
, void *opaque
,
332 MachineState
*ms
= MACHINE(obj
);
335 visit_type_OnOffSplit(v
, name
, &mode
, &err
);
337 error_propagate(errp
, err
);
341 case ON_OFF_SPLIT_ON
:
342 ms
->kernel_irqchip_allowed
= true;
343 ms
->kernel_irqchip_required
= true;
344 ms
->kernel_irqchip_split
= false;
346 case ON_OFF_SPLIT_OFF
:
347 ms
->kernel_irqchip_allowed
= false;
348 ms
->kernel_irqchip_required
= false;
349 ms
->kernel_irqchip_split
= false;
351 case ON_OFF_SPLIT_SPLIT
:
352 ms
->kernel_irqchip_allowed
= true;
353 ms
->kernel_irqchip_required
= true;
354 ms
->kernel_irqchip_split
= true;
357 /* The value was checked in visit_type_OnOffSplit() above. If
358 * we get here, then something is wrong in QEMU.
365 static void machine_get_kvm_shadow_mem(Object
*obj
, Visitor
*v
,
366 const char *name
, void *opaque
,
369 MachineState
*ms
= MACHINE(obj
);
370 int64_t value
= ms
->kvm_shadow_mem
;
372 visit_type_int(v
, name
, &value
, errp
);
375 static void machine_set_kvm_shadow_mem(Object
*obj
, Visitor
*v
,
376 const char *name
, void *opaque
,
379 MachineState
*ms
= MACHINE(obj
);
383 visit_type_int(v
, name
, &value
, &error
);
385 error_propagate(errp
, error
);
389 ms
->kvm_shadow_mem
= value
;
392 static char *machine_get_kernel(Object
*obj
, Error
**errp
)
394 MachineState
*ms
= MACHINE(obj
);
396 return g_strdup(ms
->kernel_filename
);
399 static void machine_set_kernel(Object
*obj
, const char *value
, Error
**errp
)
401 MachineState
*ms
= MACHINE(obj
);
403 g_free(ms
->kernel_filename
);
404 ms
->kernel_filename
= g_strdup(value
);
407 static char *machine_get_initrd(Object
*obj
, Error
**errp
)
409 MachineState
*ms
= MACHINE(obj
);
411 return g_strdup(ms
->initrd_filename
);
414 static void machine_set_initrd(Object
*obj
, const char *value
, Error
**errp
)
416 MachineState
*ms
= MACHINE(obj
);
418 g_free(ms
->initrd_filename
);
419 ms
->initrd_filename
= g_strdup(value
);
422 static char *machine_get_append(Object
*obj
, Error
**errp
)
424 MachineState
*ms
= MACHINE(obj
);
426 return g_strdup(ms
->kernel_cmdline
);
429 static void machine_set_append(Object
*obj
, const char *value
, Error
**errp
)
431 MachineState
*ms
= MACHINE(obj
);
433 g_free(ms
->kernel_cmdline
);
434 ms
->kernel_cmdline
= g_strdup(value
);
437 static char *machine_get_dtb(Object
*obj
, Error
**errp
)
439 MachineState
*ms
= MACHINE(obj
);
441 return g_strdup(ms
->dtb
);
444 static void machine_set_dtb(Object
*obj
, const char *value
, Error
**errp
)
446 MachineState
*ms
= MACHINE(obj
);
449 ms
->dtb
= g_strdup(value
);
452 static char *machine_get_dumpdtb(Object
*obj
, Error
**errp
)
454 MachineState
*ms
= MACHINE(obj
);
456 return g_strdup(ms
->dumpdtb
);
459 static void machine_set_dumpdtb(Object
*obj
, const char *value
, Error
**errp
)
461 MachineState
*ms
= MACHINE(obj
);
464 ms
->dumpdtb
= g_strdup(value
);
467 static void machine_get_phandle_start(Object
*obj
, Visitor
*v
,
468 const char *name
, void *opaque
,
471 MachineState
*ms
= MACHINE(obj
);
472 int64_t value
= ms
->phandle_start
;
474 visit_type_int(v
, name
, &value
, errp
);
477 static void machine_set_phandle_start(Object
*obj
, Visitor
*v
,
478 const char *name
, void *opaque
,
481 MachineState
*ms
= MACHINE(obj
);
485 visit_type_int(v
, name
, &value
, &error
);
487 error_propagate(errp
, error
);
491 ms
->phandle_start
= value
;
494 static char *machine_get_dt_compatible(Object
*obj
, Error
**errp
)
496 MachineState
*ms
= MACHINE(obj
);
498 return g_strdup(ms
->dt_compatible
);
501 static void machine_set_dt_compatible(Object
*obj
, const char *value
, Error
**errp
)
503 MachineState
*ms
= MACHINE(obj
);
505 g_free(ms
->dt_compatible
);
506 ms
->dt_compatible
= g_strdup(value
);
509 static bool machine_get_dump_guest_core(Object
*obj
, Error
**errp
)
511 MachineState
*ms
= MACHINE(obj
);
513 return ms
->dump_guest_core
;
516 static void machine_set_dump_guest_core(Object
*obj
, bool value
, Error
**errp
)
518 MachineState
*ms
= MACHINE(obj
);
520 ms
->dump_guest_core
= value
;
523 static bool machine_get_mem_merge(Object
*obj
, Error
**errp
)
525 MachineState
*ms
= MACHINE(obj
);
527 return ms
->mem_merge
;
530 static void machine_set_mem_merge(Object
*obj
, bool value
, Error
**errp
)
532 MachineState
*ms
= MACHINE(obj
);
534 ms
->mem_merge
= value
;
537 static bool machine_get_usb(Object
*obj
, Error
**errp
)
539 MachineState
*ms
= MACHINE(obj
);
544 static void machine_set_usb(Object
*obj
, bool value
, Error
**errp
)
546 MachineState
*ms
= MACHINE(obj
);
549 ms
->usb_disabled
= !value
;
552 static bool machine_get_graphics(Object
*obj
, Error
**errp
)
554 MachineState
*ms
= MACHINE(obj
);
556 return ms
->enable_graphics
;
559 static void machine_set_graphics(Object
*obj
, bool value
, Error
**errp
)
561 MachineState
*ms
= MACHINE(obj
);
563 ms
->enable_graphics
= value
;
566 static bool machine_get_igd_gfx_passthru(Object
*obj
, Error
**errp
)
568 MachineState
*ms
= MACHINE(obj
);
570 return ms
->igd_gfx_passthru
;
573 static void machine_set_igd_gfx_passthru(Object
*obj
, bool value
, Error
**errp
)
575 MachineState
*ms
= MACHINE(obj
);
577 ms
->igd_gfx_passthru
= value
;
580 static char *machine_get_firmware(Object
*obj
, Error
**errp
)
582 MachineState
*ms
= MACHINE(obj
);
584 return g_strdup(ms
->firmware
);
587 static void machine_set_firmware(Object
*obj
, const char *value
, Error
**errp
)
589 MachineState
*ms
= MACHINE(obj
);
591 g_free(ms
->firmware
);
592 ms
->firmware
= g_strdup(value
);
595 static void machine_set_suppress_vmdesc(Object
*obj
, bool value
, Error
**errp
)
597 MachineState
*ms
= MACHINE(obj
);
599 ms
->suppress_vmdesc
= value
;
602 static bool machine_get_suppress_vmdesc(Object
*obj
, Error
**errp
)
604 MachineState
*ms
= MACHINE(obj
);
606 return ms
->suppress_vmdesc
;
609 static void machine_set_enforce_config_section(Object
*obj
, bool value
,
612 MachineState
*ms
= MACHINE(obj
);
614 warn_report("enforce-config-section is deprecated, please use "
615 "-global migration.send-configuration=on|off instead");
617 ms
->enforce_config_section
= value
;
620 static bool machine_get_enforce_config_section(Object
*obj
, Error
**errp
)
622 MachineState
*ms
= MACHINE(obj
);
624 return ms
->enforce_config_section
;
627 static char *machine_get_memory_encryption(Object
*obj
, Error
**errp
)
629 MachineState
*ms
= MACHINE(obj
);
631 return g_strdup(ms
->memory_encryption
);
634 static void machine_set_memory_encryption(Object
*obj
, const char *value
,
637 MachineState
*ms
= MACHINE(obj
);
639 g_free(ms
->memory_encryption
);
640 ms
->memory_encryption
= g_strdup(value
);
643 void machine_class_allow_dynamic_sysbus_dev(MachineClass
*mc
, const char *type
)
645 strList
*item
= g_new0(strList
, 1);
647 item
->value
= g_strdup(type
);
648 item
->next
= mc
->allowed_dynamic_sysbus_devices
;
649 mc
->allowed_dynamic_sysbus_devices
= item
;
652 static void validate_sysbus_device(SysBusDevice
*sbdev
, void *opaque
)
654 MachineState
*machine
= opaque
;
655 MachineClass
*mc
= MACHINE_GET_CLASS(machine
);
656 bool allowed
= false;
659 for (wl
= mc
->allowed_dynamic_sysbus_devices
;
662 allowed
|= !!object_dynamic_cast(OBJECT(sbdev
), wl
->value
);
666 error_report("Option '-device %s' cannot be handled by this machine",
667 object_class_get_name(object_get_class(OBJECT(sbdev
))));
672 static void machine_init_notify(Notifier
*notifier
, void *data
)
674 MachineState
*machine
= MACHINE(qdev_get_machine());
677 * Loop through all dynamically created sysbus devices and check if they are
678 * all allowed. If a device is not allowed, error out.
680 foreach_dynamic_sysbus_device(validate_sysbus_device
, machine
);
683 HotpluggableCPUList
*machine_query_hotpluggable_cpus(MachineState
*machine
)
686 HotpluggableCPUList
*head
= NULL
;
687 MachineClass
*mc
= MACHINE_GET_CLASS(machine
);
689 /* force board to initialize possible_cpus if it hasn't been done yet */
690 mc
->possible_cpu_arch_ids(machine
);
692 for (i
= 0; i
< machine
->possible_cpus
->len
; i
++) {
694 HotpluggableCPUList
*list_item
= g_new0(typeof(*list_item
), 1);
695 HotpluggableCPU
*cpu_item
= g_new0(typeof(*cpu_item
), 1);
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
));
702 cpu
= machine
->possible_cpus
->cpus
[i
].cpu
;
704 cpu_item
->has_qom_path
= true;
705 cpu_item
->qom_path
= object_get_canonical_path(cpu
);
707 list_item
->value
= cpu_item
;
708 list_item
->next
= head
;
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
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.
726 * However for CLI convenience it's possible to pass in subset of properties,
727 * which would affect all cpu slots that match it.
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.
735 * On attempt of reassigning (already assigned) cpu slot to another NUMA node,
737 * Empty subset is disallowed and function will return with error in this case.
739 void machine_set_cpu_numa_node(MachineState
*machine
,
740 const CpuInstanceProperties
*props
, Error
**errp
)
742 MachineClass
*mc
= MACHINE_GET_CLASS(machine
);
746 if (!mc
->possible_cpu_arch_ids
) {
747 error_setg(errp
, "mapping of CPUs to NUMA node is not supported");
751 /* disabling node mapping is not supported, forbid it */
752 assert(props
->has_node_id
);
754 /* force board to initialize possible_cpus if it hasn't been done yet */
755 mc
->possible_cpu_arch_ids(machine
);
757 for (i
= 0; i
< machine
->possible_cpus
->len
; i
++) {
758 CPUArchId
*slot
= &machine
->possible_cpus
->cpus
[i
];
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");
766 if (props
->has_core_id
&& !slot
->props
.has_core_id
) {
767 error_setg(errp
, "core-id is not supported");
771 if (props
->has_socket_id
&& !slot
->props
.has_socket_id
) {
772 error_setg(errp
, "socket-id is not supported");
776 /* skip slots with explicit mismatch */
777 if (props
->has_thread_id
&& props
->thread_id
!= slot
->props
.thread_id
) {
781 if (props
->has_core_id
&& props
->core_id
!= slot
->props
.core_id
) {
785 if (props
->has_socket_id
&& props
->socket_id
!= slot
->props
.socket_id
) {
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
);
799 /* assign slot to node as it's matched '-numa cpu' key */
801 slot
->props
.node_id
= props
->node_id
;
802 slot
->props
.has_node_id
= props
->has_node_id
;
806 error_setg(errp
, "no match found");
810 static void machine_class_init(ObjectClass
*oc
, void *data
)
812 MachineClass
*mc
= MACHINE_CLASS(oc
);
814 /* Default 128 MB as guest ram size */
815 mc
->default_ram_size
= 128 * MiB
;
816 mc
->rom_file_has_mr
= true;
818 /* numa node memory size aligned on 8MB by default.
819 * On Linux, each node's border has to be 8MB aligned
821 mc
->numa_mem_align_shift
= 23;
822 mc
->numa_auto_assign_ram
= numa_default_auto_assign_ram
;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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",
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
);
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
);
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
);
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
);
898 object_class_property_add_bool(oc
, "igd-passthru",
899 machine_get_igd_gfx_passthru
, machine_set_igd_gfx_passthru
,
901 object_class_property_set_description(oc
, "igd-passthru",
902 "Set on/off to enable/disable igd passthrou", &error_abort
);
904 object_class_property_add_str(oc
, "firmware",
905 machine_get_firmware
, machine_set_firmware
,
907 object_class_property_set_description(oc
, "firmware",
908 "Firmware image", &error_abort
);
910 object_class_property_add_bool(oc
, "suppress-vmdesc",
911 machine_get_suppress_vmdesc
, machine_set_suppress_vmdesc
,
913 object_class_property_set_description(oc
, "suppress-vmdesc",
914 "Set on to disable self-describing migration", &error_abort
);
916 object_class_property_add_bool(oc
, "enforce-config-section",
917 machine_get_enforce_config_section
, machine_set_enforce_config_section
,
919 object_class_property_set_description(oc
, "enforce-config-section",
920 "Set on to enforce configuration section migration", &error_abort
);
922 object_class_property_add_str(oc
, "memory-encryption",
923 machine_get_memory_encryption
, machine_set_memory_encryption
,
925 object_class_property_set_description(oc
, "memory-encryption",
926 "Set memory encryption object to use", &error_abort
);
929 static void machine_class_base_init(ObjectClass
*oc
, void *data
)
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();
941 static void machine_initfn(Object
*obj
)
943 MachineState
*ms
= MACHINE(obj
);
944 MachineClass
*mc
= MACHINE_GET_CLASS(obj
);
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;
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
);
958 static void machine_finalize(Object
*obj
)
960 MachineState
*ms
= MACHINE(obj
);
963 g_free(ms
->kernel_filename
);
964 g_free(ms
->initrd_filename
);
965 g_free(ms
->kernel_cmdline
);
968 g_free(ms
->dt_compatible
);
969 g_free(ms
->firmware
);
970 g_free(ms
->device_memory
);
973 bool machine_usb(MachineState
*machine
)
978 bool machine_kernel_irqchip_allowed(MachineState
*machine
)
980 return machine
->kernel_irqchip_allowed
;
983 bool machine_kernel_irqchip_required(MachineState
*machine
)
985 return machine
->kernel_irqchip_required
;
988 bool machine_kernel_irqchip_split(MachineState
*machine
)
990 return machine
->kernel_irqchip_split
;
993 int machine_kvm_shadow_mem(MachineState
*machine
)
995 return machine
->kvm_shadow_mem
;
998 int machine_phandle_start(MachineState
*machine
)
1000 return machine
->phandle_start
;
1003 bool machine_dump_guest_core(MachineState
*machine
)
1005 return machine
->dump_guest_core
;
1008 bool machine_mem_merge(MachineState
*machine
)
1010 return machine
->mem_merge
;
1013 static char *cpu_slot_to_string(const CPUArchId
*cpu
)
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
);
1019 if (cpu
->props
.has_core_id
) {
1021 g_string_append_printf(s
, ", ");
1023 g_string_append_printf(s
, "core-id: %"PRId64
, cpu
->props
.core_id
);
1025 if (cpu
->props
.has_thread_id
) {
1027 g_string_append_printf(s
, ", ");
1029 g_string_append_printf(s
, "thread-id: %"PRId64
, cpu
->props
.thread_id
);
1031 return g_string_free(s
, false);
1034 static void machine_numa_finish_cpu_init(MachineState
*machine
)
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
);
1042 assert(nb_numa_nodes
);
1043 for (i
= 0; i
< possible_cpus
->len
; i
++) {
1044 if (possible_cpus
->cpus
[i
].props
.has_node_id
) {
1048 default_mapping
= (i
== possible_cpus
->len
);
1050 for (i
= 0; i
< possible_cpus
->len
; i
++) {
1051 const CPUArchId
*cpu_slot
= &possible_cpus
->cpus
[i
];
1053 if (!cpu_slot
->props
.has_node_id
) {
1054 /* fetch default mapping from board and enable it */
1055 CpuInstanceProperties props
= cpu_slot
->props
;
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
);
1066 /* non mapped cpus used to fallback to node 0 */
1070 props
.has_node_id
= true;
1071 machine_set_cpu_numa_node(machine
, &props
, &error_fatal
);
1074 if (s
->len
&& !qtest_enabled()) {
1075 warn_report("CPU(s) not present in any NUMA nodes: %s",
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");
1081 g_string_free(s
, true);
1084 void machine_run_board_init(MachineState
*machine
)
1086 MachineClass
*machine_class
= MACHINE_GET_CLASS(machine
);
1088 numa_complete_configuration(machine
);
1089 if (nb_numa_nodes
) {
1090 machine_numa_finish_cpu_init(machine
);
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.
1096 if (machine_class
->valid_cpu_types
&& machine
->cpu_type
) {
1097 ObjectClass
*class = object_class_by_name(machine
->cpu_type
);
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
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
]);
1124 machine_class
->init(machine
);
1127 static const TypeInfo machine_info
= {
1128 .name
= TYPE_MACHINE
,
1129 .parent
= TYPE_OBJECT
,
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
,
1139 static void machine_register_types(void)
1141 type_register_static(&machine_info
);
1144 type_init(machine_register_types
)