2014-03-05 18:30:45 +01:00
|
|
|
/*
|
|
|
|
* QEMU Machine
|
|
|
|
*
|
|
|
|
* Copyright (C) 2014 Red Hat Inc
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Marcel Apfelbaum <marcel.a@redhat.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
|
|
* See the COPYING file in the top-level directory.
|
|
|
|
*/
|
|
|
|
|
2016-01-26 19:17:29 +01:00
|
|
|
#include "qemu/osdep.h"
|
2019-06-20 07:45:24 +02:00
|
|
|
#include "qemu/option.h"
|
|
|
|
#include "qapi/qmp/qerror.h"
|
|
|
|
#include "sysemu/replay.h"
|
2018-06-25 14:41:58 +02:00
|
|
|
#include "qemu/units.h"
|
2014-03-05 18:30:45 +01:00
|
|
|
#include "hw/boards.h"
|
2020-11-13 08:43:56 +01:00
|
|
|
#include "hw/loader.h"
|
include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef. Since then, we've moved to include qemu/osdep.h
everywhere. Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h. That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h. Include qapi/error.h in .c files that need it and don't
get it now. Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly. Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h. Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third. Unfortunately, the number depending on
qapi-types.h shrinks only a little. More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-03-14 09:01:28 +01:00
|
|
|
#include "qapi/error.h"
|
2018-02-11 10:36:01 +01:00
|
|
|
#include "qapi/qapi-visit-common.h"
|
2014-05-26 14:40:58 +02:00
|
|
|
#include "qapi/visitor.h"
|
2014-07-01 16:14:41 +02:00
|
|
|
#include "hw/sysbus.h"
|
2020-11-13 08:43:56 +01:00
|
|
|
#include "sysemu/cpus.h"
|
2014-07-01 16:14:41 +02:00
|
|
|
#include "sysemu/sysemu.h"
|
2020-11-13 08:43:56 +01:00
|
|
|
#include "sysemu/reset.h"
|
|
|
|
#include "sysemu/runstate.h"
|
2017-05-02 18:29:55 +02:00
|
|
|
#include "sysemu/numa.h"
|
2014-07-01 16:14:41 +02:00
|
|
|
#include "qemu/error-report.h"
|
2017-05-18 10:09:31 +02:00
|
|
|
#include "sysemu/qtest.h"
|
2018-12-12 16:36:30 +01:00
|
|
|
#include "hw/pci/pci.h"
|
2019-03-08 19:20:53 +01:00
|
|
|
#include "hw/mem/nvdimm.h"
|
2020-11-13 08:43:56 +01:00
|
|
|
#include "migration/global_state.h"
|
2020-02-19 17:08:38 +01:00
|
|
|
#include "migration/vmstate.h"
|
2014-05-26 14:40:58 +02:00
|
|
|
|
2020-11-09 18:39:28 +01:00
|
|
|
GlobalProperty hw_compat_5_2[] = {};
|
|
|
|
const size_t hw_compat_5_2_len = G_N_ELEMENTS(hw_compat_5_2);
|
|
|
|
|
2020-08-18 16:33:46 +02:00
|
|
|
GlobalProperty hw_compat_5_1[] = {
|
|
|
|
{ "vhost-scsi", "num_queues", "1"},
|
2020-08-18 16:33:48 +02:00
|
|
|
{ "vhost-user-blk", "num-queues", "1"},
|
2020-08-18 16:33:46 +02:00
|
|
|
{ "vhost-user-scsi", "num_queues", "1"},
|
2020-08-18 16:33:47 +02:00
|
|
|
{ "virtio-blk-device", "num-queues", "1"},
|
2020-08-18 16:33:46 +02:00
|
|
|
{ "virtio-scsi-device", "num_queues", "1"},
|
2019-09-27 11:43:12 +02:00
|
|
|
{ "nvme", "use-intel-id", "on"},
|
2020-11-09 14:53:04 +01:00
|
|
|
{ "pvpanic", "events", "1"}, /* PVPANIC_PANICKED */
|
2020-08-18 16:33:46 +02:00
|
|
|
};
|
2020-08-19 16:40:16 +02:00
|
|
|
const size_t hw_compat_5_1_len = G_N_ELEMENTS(hw_compat_5_1);
|
|
|
|
|
2020-05-27 06:14:00 +02:00
|
|
|
GlobalProperty hw_compat_5_0[] = {
|
hw/pci-host: save/restore pci host config register
The pci host config register is used to save PCI address for
read/write config data. If guest writes a value to config register,
and then QEMU pauses the vcpu to migrate, after the migration, the guest
will continue to write pci config data, and the write data will be ignored
because of new qemu process losing the config register state.
To trigger the bug:
1. guest is booting in seabios.
2. guest enables the SMRAM in seabios:piix4_apmc_smm_setup, and then
expects to disable the SMRAM by pci_config_writeb.
3. after guest writes the pci host config register, QEMU pauses vcpu
to finish migration.
4. guest write of config data(0x0A) fails to disable the SMRAM because
the config register state is lost.
5. guest continues to boot and crashes in ipxe option ROM due to SMRAM
in enabled state.
Example Reproducer:
step 1. Make modifications to seabios and qemu for increase reproduction
efficiency, write 0xf0 to 0x402 port notify qemu to stop vcpu after
0x0cf8 port wrote i440 configure register. qemu stop vcpu when catch
0x402 port wrote 0xf0.
seabios:/src/hw/pci.c
@@ -52,6 +52,11 @@ void pci_config_writeb(u16 bdf, u32 addr, u8 val)
writeb(mmconfig_addr(bdf, addr), val);
} else {
outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+ if (bdf == 0 && addr == 0x72 && val == 0xa) {
+ dprintf(1, "stop vcpu\n");
+ outb(0xf0, 0x402); // notify qemu to stop vcpu
+ dprintf(1, "resume vcpu\n");
+ }
outb(val, PORT_PCI_DATA + (addr & 3));
}
}
qemu:hw/char/debugcon.c
@@ -60,6 +61,9 @@ static void debugcon_ioport_write(void *opaque, hwaddr addr, uint64_t val,
printf(" [debugcon: write addr=0x%04" HWADDR_PRIx " val=0x%02" PRIx64 "]\n", addr, val);
#endif
+ if (ch == 0xf0) {
+ vm_stop(RUN_STATE_PAUSED);
+ }
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &ch, 1);
step 2. start vm1 by the following command line, and then vm stopped.
$ qemu-system-x86_64 -machine pc-i440fx-5.0,accel=kvm\
-netdev tap,ifname=tap-test,id=hostnet0,vhost=on,downscript=no,script=no\
-device virtio-net-pci,netdev=hostnet0,id=net0,bus=pci.0,addr=0x13,bootindex=3\
-device cirrus-vga,id=video0,vgamem_mb=16,bus=pci.0,addr=0x2\
-chardev file,id=seabios,path=/var/log/test.seabios,append=on\
-device isa-debugcon,iobase=0x402,chardev=seabios\
-monitor stdio
step 3. start vm2 to accept vm1 state.
$ qemu-system-x86_64 -machine pc-i440fx-5.0,accel=kvm\
-netdev tap,ifname=tap-test1,id=hostnet0,vhost=on,downscript=no,script=no\
-device virtio-net-pci,netdev=hostnet0,id=net0,bus=pci.0,addr=0x13,bootindex=3\
-device cirrus-vga,id=video0,vgamem_mb=16,bus=pci.0,addr=0x2\
-chardev file,id=seabios,path=/var/log/test.seabios,append=on\
-device isa-debugcon,iobase=0x402,chardev=seabios\
-monitor stdio \
-incoming tcp:127.0.0.1:8000
step 4. execute the following qmp command in vm1 to migrate.
(qemu) migrate tcp:127.0.0.1:8000
step 5. execute the following qmp command in vm2 to resume vcpu.
(qemu) cont
Before this patch, we get KVM "emulation failure" error on vm2.
This patch fixes it.
Cc: qemu-stable@nongnu.org
Signed-off-by: Hogan Wang <hogan.wang@huawei.com>
Message-Id: <20200727084621.3279-1-hogan.wang@huawei.com>
Reported-by: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2020-07-27 10:46:20 +02:00
|
|
|
{ "pci-host-bridge", "x-config-reg-migration-enabled", "off" },
|
2020-05-27 06:14:00 +02:00
|
|
|
{ "virtio-balloon-device", "page-poison", "false" },
|
2020-06-23 12:28:08 +02:00
|
|
|
{ "vmport", "x-read-set-eax", "off" },
|
|
|
|
{ "vmport", "x-signal-unsupported-cmd", "off" },
|
|
|
|
{ "vmport", "x-report-vmx-type", "off" },
|
|
|
|
{ "vmport", "x-cmds-v2", "off" },
|
2020-09-21 14:25:03 +02:00
|
|
|
{ "virtio-device", "x-disable-legacy-check", "true" },
|
2020-05-27 06:14:00 +02:00
|
|
|
};
|
2020-04-29 16:46:05 +02:00
|
|
|
const size_t hw_compat_5_0_len = G_N_ELEMENTS(hw_compat_5_0);
|
|
|
|
|
2019-11-05 19:22:17 +01:00
|
|
|
GlobalProperty hw_compat_4_2[] = {
|
2020-02-14 08:46:48 +01:00
|
|
|
{ "virtio-blk-device", "queue-size", "128"},
|
|
|
|
{ "virtio-scsi-device", "virtqueue_size", "128"},
|
2019-11-05 19:22:17 +01:00
|
|
|
{ "virtio-blk-device", "x-enable-wce-if-config-wce", "off" },
|
2019-12-20 15:09:04 +01:00
|
|
|
{ "virtio-blk-device", "seg-max-adjust", "off"},
|
|
|
|
{ "virtio-scsi-device", "seg_max_adjust", "off"},
|
|
|
|
{ "vhost-blk-device", "seg_max_adjust", "off"},
|
2020-01-08 10:10:43 +01:00
|
|
|
{ "usb-host", "suppress-remote-wake", "off" },
|
2020-01-08 10:10:44 +01:00
|
|
|
{ "usb-redir", "suppress-remote-wake", "off" },
|
2020-02-06 08:43:58 +01:00
|
|
|
{ "qxl", "revision", "4" },
|
|
|
|
{ "qxl-vga", "revision", "4" },
|
2020-04-03 12:18:26 +02:00
|
|
|
{ "fw_cfg", "acpi-mr-restore", "false" },
|
2021-01-08 18:12:52 +01:00
|
|
|
{ "virtio-device", "use-disabled-flag", "false" },
|
2019-11-05 19:22:17 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_4_2_len = G_N_ELEMENTS(hw_compat_4_2);
|
|
|
|
|
2019-08-20 18:30:05 +02:00
|
|
|
GlobalProperty hw_compat_4_1[] = {
|
|
|
|
{ "virtio-pci", "x-pcie-flr-init", "off" },
|
|
|
|
};
|
2019-07-24 12:35:24 +02:00
|
|
|
const size_t hw_compat_4_1_len = G_N_ELEMENTS(hw_compat_4_1);
|
|
|
|
|
2019-06-14 15:09:02 +02:00
|
|
|
GlobalProperty hw_compat_4_0[] = {
|
2019-06-07 10:34:44 +02:00
|
|
|
{ "VGA", "edid", "false" },
|
|
|
|
{ "secondary-vga", "edid", "false" },
|
|
|
|
{ "bochs-display", "edid", "false" },
|
|
|
|
{ "virtio-vga", "edid", "false" },
|
2020-03-18 10:39:19 +01:00
|
|
|
{ "virtio-gpu-device", "edid", "false" },
|
2019-06-26 04:31:26 +02:00
|
|
|
{ "virtio-device", "use-started", "false" },
|
2019-07-10 16:14:40 +02:00
|
|
|
{ "virtio-balloon-device", "qemu-4-0-config-size", "true" },
|
2019-07-15 15:17:04 +02:00
|
|
|
{ "pl031", "migrate-tick-offset", "false" },
|
2019-06-07 10:34:44 +02:00
|
|
|
};
|
2019-04-11 12:20:25 +02:00
|
|
|
const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_3_1[] = {
|
2019-01-07 20:30:20 +01:00
|
|
|
{ "pcie-root-port", "x-speed", "2_5" },
|
|
|
|
{ "pcie-root-port", "x-width", "1" },
|
|
|
|
{ "memory-backend-file", "x-use-canonical-path-for-ramblock-id", "true" },
|
|
|
|
{ "memory-backend-memfd", "x-use-canonical-path-for-ramblock-id", "true" },
|
2019-01-14 23:27:49 +01:00
|
|
|
{ "tpm-crb", "ppi", "false" },
|
|
|
|
{ "tpm-tis", "ppi", "false" },
|
2019-01-10 13:51:08 +01:00
|
|
|
{ "usb-kbd", "serial", "42" },
|
|
|
|
{ "usb-mouse", "serial", "42" },
|
2019-05-20 10:18:05 +02:00
|
|
|
{ "usb-tablet", "serial", "42" },
|
2019-02-21 11:33:07 +01:00
|
|
|
{ "virtio-blk-device", "discard", "false" },
|
|
|
|
{ "virtio-blk-device", "write-zeroes", "false" },
|
2019-07-10 16:14:40 +02:00
|
|
|
{ "virtio-balloon-device", "qemu-4-0-config-size", "false" },
|
2019-07-30 11:37:19 +02:00
|
|
|
{ "pcie-root-port-base", "disable-acs", "true" }, /* Added in 4.1 */
|
2018-12-12 16:36:30 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_3_0[] = {};
|
|
|
|
const size_t hw_compat_3_0_len = G_N_ELEMENTS(hw_compat_3_0);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_2_12[] = {
|
2019-01-07 20:30:20 +01:00
|
|
|
{ "migration", "decompress-error-check", "off" },
|
|
|
|
{ "hda-audio", "use-timer", "false" },
|
|
|
|
{ "cirrus-vga", "global-vmstate", "true" },
|
|
|
|
{ "VGA", "global-vmstate", "true" },
|
|
|
|
{ "vmware-svga", "global-vmstate", "true" },
|
|
|
|
{ "qxl-vga", "global-vmstate", "true" },
|
2018-12-12 16:36:30 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_2_12_len = G_N_ELEMENTS(hw_compat_2_12);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_2_11[] = {
|
2019-01-07 20:30:20 +01:00
|
|
|
{ "hpet", "hpet-offset-saved", "false" },
|
|
|
|
{ "virtio-blk-pci", "vectors", "2" },
|
|
|
|
{ "vhost-user-blk-pci", "vectors", "2" },
|
|
|
|
{ "e1000", "migrate_tso_props", "off" },
|
2018-12-12 16:36:30 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_2_11_len = G_N_ELEMENTS(hw_compat_2_11);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_2_10[] = {
|
2019-01-07 20:30:20 +01:00
|
|
|
{ "virtio-mouse-device", "wheel-axis", "false" },
|
|
|
|
{ "virtio-tablet-device", "wheel-axis", "false" },
|
2018-12-12 16:36:30 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_2_10_len = G_N_ELEMENTS(hw_compat_2_10);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_2_9[] = {
|
2019-01-07 20:30:20 +01:00
|
|
|
{ "pci-bridge", "shpc", "off" },
|
|
|
|
{ "intel-iommu", "pt", "off" },
|
|
|
|
{ "virtio-net-device", "x-mtu-bypass-backend", "off" },
|
|
|
|
{ "pcie-root-port", "x-migrate-msix", "false" },
|
2018-12-12 16:36:30 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_2_9_len = G_N_ELEMENTS(hw_compat_2_9);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_2_8[] = {
|
2019-01-07 20:30:20 +01:00
|
|
|
{ "fw_cfg_mem", "x-file-slots", "0x10" },
|
|
|
|
{ "fw_cfg_io", "x-file-slots", "0x10" },
|
|
|
|
{ "pflash_cfi01", "old-multiple-chip-handling", "on" },
|
|
|
|
{ "pci-bridge", "shpc", "on" },
|
|
|
|
{ TYPE_PCI_DEVICE, "x-pcie-extcap-init", "off" },
|
|
|
|
{ "virtio-pci", "x-pcie-deverr-init", "off" },
|
|
|
|
{ "virtio-pci", "x-pcie-lnkctl-init", "off" },
|
|
|
|
{ "virtio-pci", "x-pcie-pm-init", "off" },
|
|
|
|
{ "cirrus-vga", "vgamem_mb", "8" },
|
|
|
|
{ "isa-cirrus-vga", "vgamem_mb", "8" },
|
2018-12-12 16:36:30 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_2_8_len = G_N_ELEMENTS(hw_compat_2_8);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_2_7[] = {
|
2019-01-07 20:30:20 +01:00
|
|
|
{ "virtio-pci", "page-per-vq", "on" },
|
|
|
|
{ "virtio-serial-device", "emergency-write", "off" },
|
|
|
|
{ "ioapic", "version", "0x11" },
|
|
|
|
{ "intel-iommu", "x-buggy-eim", "true" },
|
|
|
|
{ "virtio-pci", "x-ignore-backend-features", "on" },
|
2018-12-12 16:36:30 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_2_7_len = G_N_ELEMENTS(hw_compat_2_7);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_2_6[] = {
|
2019-01-07 20:30:20 +01:00
|
|
|
{ "virtio-mmio", "format_transport_address", "off" },
|
2019-07-29 18:29:03 +02:00
|
|
|
/* Optional because not all virtio-pci devices support legacy mode */
|
|
|
|
{ "virtio-pci", "disable-modern", "on", .optional = true },
|
|
|
|
{ "virtio-pci", "disable-legacy", "off", .optional = true },
|
2018-12-12 16:36:30 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_2_6_len = G_N_ELEMENTS(hw_compat_2_6);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_2_5[] = {
|
2019-01-07 20:30:20 +01:00
|
|
|
{ "isa-fdc", "fallback", "144" },
|
|
|
|
{ "pvscsi", "x-old-pci-configuration", "on" },
|
|
|
|
{ "pvscsi", "x-disable-pcie", "on" },
|
|
|
|
{ "vmxnet3", "x-old-msi-offsets", "on" },
|
|
|
|
{ "vmxnet3", "x-disable-pcie", "on" },
|
2018-12-12 16:36:30 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_2_5_len = G_N_ELEMENTS(hw_compat_2_5);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_2_4[] = {
|
2020-02-07 01:14:04 +01:00
|
|
|
/* Optional because the 'scsi' property is Linux-only */
|
|
|
|
{ "virtio-blk-device", "scsi", "true", .optional = true },
|
2019-01-07 20:30:20 +01:00
|
|
|
{ "e1000", "extra_mac_registers", "off" },
|
|
|
|
{ "virtio-pci", "x-disable-pcie", "on" },
|
|
|
|
{ "virtio-pci", "migrate-extra", "off" },
|
|
|
|
{ "fw_cfg_mem", "dma_enabled", "off" },
|
|
|
|
{ "fw_cfg_io", "dma_enabled", "off" }
|
2018-12-12 16:36:30 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_2_4_len = G_N_ELEMENTS(hw_compat_2_4);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_2_3[] = {
|
2019-01-07 20:30:20 +01:00
|
|
|
{ "virtio-blk-pci", "any_layout", "off" },
|
|
|
|
{ "virtio-balloon-pci", "any_layout", "off" },
|
|
|
|
{ "virtio-serial-pci", "any_layout", "off" },
|
|
|
|
{ "virtio-9p-pci", "any_layout", "off" },
|
|
|
|
{ "virtio-rng-pci", "any_layout", "off" },
|
|
|
|
{ TYPE_PCI_DEVICE, "x-pcie-lnksta-dllla", "off" },
|
|
|
|
{ "migration", "send-configuration", "off" },
|
|
|
|
{ "migration", "send-section-footer", "off" },
|
|
|
|
{ "migration", "store-global-state", "off" },
|
2018-12-12 16:36:30 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_2_3_len = G_N_ELEMENTS(hw_compat_2_3);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_2_2[] = {};
|
|
|
|
const size_t hw_compat_2_2_len = G_N_ELEMENTS(hw_compat_2_2);
|
|
|
|
|
2018-12-12 16:36:30 +01:00
|
|
|
GlobalProperty hw_compat_2_1[] = {
|
2019-01-07 20:30:20 +01:00
|
|
|
{ "intel-hda", "old_msi_addr", "on" },
|
|
|
|
{ "VGA", "qemu-extended-regs", "off" },
|
|
|
|
{ "secondary-vga", "qemu-extended-regs", "off" },
|
|
|
|
{ "virtio-scsi-pci", "any_layout", "off" },
|
|
|
|
{ "usb-mouse", "usb_version", "1" },
|
|
|
|
{ "usb-kbd", "usb_version", "1" },
|
|
|
|
{ "virtio-pci", "virtio-pci-bus-master-bug-migration", "on" },
|
2018-12-12 16:36:30 +01:00
|
|
|
};
|
|
|
|
const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1);
|
|
|
|
|
2020-10-28 13:04:08 +01:00
|
|
|
MachineState *current_machine;
|
|
|
|
|
2014-05-26 14:40:58 +02:00
|
|
|
static char *machine_get_kernel(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return g_strdup(ms->kernel_filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_kernel(Object *obj, const char *value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
2014-08-06 20:18:21 +02:00
|
|
|
g_free(ms->kernel_filename);
|
2014-05-26 14:40:58 +02:00
|
|
|
ms->kernel_filename = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *machine_get_initrd(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return g_strdup(ms->initrd_filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_initrd(Object *obj, const char *value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
2014-08-06 20:18:21 +02:00
|
|
|
g_free(ms->initrd_filename);
|
2014-05-26 14:40:58 +02:00
|
|
|
ms->initrd_filename = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *machine_get_append(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return g_strdup(ms->kernel_cmdline);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_append(Object *obj, const char *value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
2014-08-06 20:18:21 +02:00
|
|
|
g_free(ms->kernel_cmdline);
|
2014-05-26 14:40:58 +02:00
|
|
|
ms->kernel_cmdline = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *machine_get_dtb(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return g_strdup(ms->dtb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_dtb(Object *obj, const char *value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
2014-08-06 20:18:21 +02:00
|
|
|
g_free(ms->dtb);
|
2014-05-26 14:40:58 +02:00
|
|
|
ms->dtb = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *machine_get_dumpdtb(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return g_strdup(ms->dumpdtb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
2014-08-06 20:18:21 +02:00
|
|
|
g_free(ms->dumpdtb);
|
2014-05-26 14:40:58 +02:00
|
|
|
ms->dumpdtb = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_get_phandle_start(Object *obj, Visitor *v,
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 14:48:55 +01:00
|
|
|
const char *name, void *opaque,
|
|
|
|
Error **errp)
|
2014-05-26 14:40:58 +02:00
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
int64_t value = ms->phandle_start;
|
|
|
|
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 14:48:54 +01:00
|
|
|
visit_type_int(v, name, &value, errp);
|
2014-05-26 14:40:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_phandle_start(Object *obj, Visitor *v,
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 14:48:55 +01:00
|
|
|
const char *name, void *opaque,
|
|
|
|
Error **errp)
|
2014-05-26 14:40:58 +02:00
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
int64_t value;
|
|
|
|
|
error: Eliminate error_propagate() with Coccinelle, part 1
When all we do with an Error we receive into a local variable is
propagating to somewhere else, we can just as well receive it there
right away. Convert
if (!foo(..., &err)) {
...
error_propagate(errp, err);
...
return ...
}
to
if (!foo(..., errp)) {
...
...
return ...
}
where nothing else needs @err. Coccinelle script:
@rule1 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
binary operator op;
constant c1, c2;
symbol false;
@@
if (
(
- fun(args, &err, args2)
+ fun(args, errp, args2)
|
- !fun(args, &err, args2)
+ !fun(args, errp, args2)
|
- fun(args, &err, args2) op c1
+ fun(args, errp, args2) op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
)
}
@rule2 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
expression var;
binary operator op;
constant c1, c2;
symbol false;
@@
- var = fun(args, &err, args2);
+ var = fun(args, errp, args2);
... when != err
if (
(
var
|
!var
|
var op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
|
return var;
)
}
@depends on rule1 || rule2@
identifier err;
@@
- Error *err = NULL;
... when != err
Not exactly elegant, I'm afraid.
The "when != lbl:" is necessary to avoid transforming
if (fun(args, &err)) {
goto out
}
...
out:
error_propagate(errp, err);
even though other paths to label out still need the error_propagate().
For an actual example, see sclp_realize().
Without the "when strict", Coccinelle transforms vfio_msix_setup(),
incorrectly. I don't know what exactly "when strict" does, only that
it helps here.
The match of return is narrower than what I want, but I can't figure
out how to express "return where the operand doesn't use @err". For
an example where it's too narrow, see vfio_intx_enable().
Silently fails to convert hw/arm/armsse.c, because Coccinelle gets
confused by ARMSSE being used both as typedef and function-like macro
there. Converted manually.
Line breaks tidied up manually. One nested declaration of @local_err
deleted manually. Preexisting unwanted blank line dropped in
hw/riscv/sifive_e.c.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200707160613.848843-35-armbru@redhat.com>
2020-07-07 18:06:02 +02:00
|
|
|
if (!visit_type_int(v, name, &value, errp)) {
|
2014-05-26 14:40:58 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ms->phandle_start = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *machine_get_dt_compatible(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return g_strdup(ms->dt_compatible);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
2014-08-06 20:18:21 +02:00
|
|
|
g_free(ms->dt_compatible);
|
2014-05-26 14:40:58 +02:00
|
|
|
ms->dt_compatible = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool machine_get_dump_guest_core(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return ms->dump_guest_core;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
ms->dump_guest_core = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool machine_get_mem_merge(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return ms->mem_merge;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_mem_merge(Object *obj, bool value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
ms->mem_merge = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool machine_get_usb(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return ms->usb;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_usb(Object *obj, bool value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
ms->usb = value;
|
2015-03-23 18:05:28 +01:00
|
|
|
ms->usb_disabled = !value;
|
2014-05-26 14:40:58 +02:00
|
|
|
}
|
|
|
|
|
2016-04-19 21:55:25 +02:00
|
|
|
static bool machine_get_graphics(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return ms->enable_graphics;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_graphics(Object *obj, bool value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
ms->enable_graphics = value;
|
|
|
|
}
|
|
|
|
|
2014-05-26 14:40:58 +02:00
|
|
|
static char *machine_get_firmware(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return g_strdup(ms->firmware);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_firmware(Object *obj, const char *value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
2014-08-06 20:18:21 +02:00
|
|
|
g_free(ms->firmware);
|
2014-05-26 14:40:58 +02:00
|
|
|
ms->firmware = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
2015-02-23 13:56:42 +01:00
|
|
|
static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
ms->suppress_vmdesc = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool machine_get_suppress_vmdesc(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return ms->suppress_vmdesc;
|
|
|
|
}
|
|
|
|
|
2018-03-08 13:48:38 +01:00
|
|
|
static char *machine_get_memory_encryption(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return g_strdup(ms->memory_encryption);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_memory_encryption(Object *obj, const char *value,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
g_free(ms->memory_encryption);
|
|
|
|
ms->memory_encryption = g_strdup(value);
|
2020-01-30 18:50:46 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* With memory encryption, the host can't see the real contents of RAM,
|
|
|
|
* so there's no point in it trying to merge areas.
|
|
|
|
*/
|
|
|
|
if (value) {
|
|
|
|
machine_set_mem_merge(obj, false, errp);
|
|
|
|
}
|
2018-03-08 13:48:38 +01:00
|
|
|
}
|
|
|
|
|
2019-03-08 19:20:53 +01:00
|
|
|
static bool machine_get_nvdimm(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return ms->nvdimms_state->is_enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_nvdimm(Object *obj, bool value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
ms->nvdimms_state->is_enabled = value;
|
|
|
|
}
|
|
|
|
|
2019-12-13 02:19:22 +01:00
|
|
|
static bool machine_get_hmat(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return ms->numa_state->hmat_enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_hmat(Object *obj, bool value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
ms->numa_state->hmat_enabled = value;
|
|
|
|
}
|
|
|
|
|
2019-03-08 19:20:53 +01:00
|
|
|
static char *machine_get_nvdimm_persistence(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return g_strdup(ms->nvdimms_state->persistence_string);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_nvdimm_persistence(Object *obj, const char *value,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
NVDIMMState *nvdimms_state = ms->nvdimms_state;
|
|
|
|
|
|
|
|
if (strcmp(value, "cpu") == 0) {
|
|
|
|
nvdimms_state->persistence = 3;
|
|
|
|
} else if (strcmp(value, "mem-ctrl") == 0) {
|
|
|
|
nvdimms_state->persistence = 2;
|
|
|
|
} else {
|
|
|
|
error_setg(errp, "-machine nvdimm-persistence=%s: unsupported option",
|
|
|
|
value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(nvdimms_state->persistence_string);
|
|
|
|
nvdimms_state->persistence_string = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
2017-11-25 16:16:05 +01:00
|
|
|
void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type)
|
2014-07-01 16:14:41 +02:00
|
|
|
{
|
2020-11-13 02:13:37 +01:00
|
|
|
QAPI_LIST_PREPEND(mc->allowed_dynamic_sysbus_devices, g_strdup(type));
|
2014-07-01 16:14:41 +02:00
|
|
|
}
|
|
|
|
|
2017-11-25 16:16:05 +01:00
|
|
|
static void validate_sysbus_device(SysBusDevice *sbdev, void *opaque)
|
2014-07-01 16:14:41 +02:00
|
|
|
{
|
2017-11-25 16:16:05 +01:00
|
|
|
MachineState *machine = opaque;
|
|
|
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
|
|
|
bool allowed = false;
|
|
|
|
strList *wl;
|
2014-07-01 16:14:41 +02:00
|
|
|
|
2017-11-25 16:16:05 +01:00
|
|
|
for (wl = mc->allowed_dynamic_sysbus_devices;
|
|
|
|
!allowed && wl;
|
|
|
|
wl = wl->next) {
|
|
|
|
allowed |= !!object_dynamic_cast(OBJECT(sbdev), wl->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!allowed) {
|
|
|
|
error_report("Option '-device %s' cannot be handled by this machine",
|
|
|
|
object_class_get_name(object_get_class(OBJECT(sbdev))));
|
|
|
|
exit(1);
|
2014-07-01 16:14:41 +02:00
|
|
|
}
|
2017-11-25 16:16:05 +01:00
|
|
|
}
|
|
|
|
|
2020-02-19 17:08:36 +01:00
|
|
|
static char *machine_get_memdev(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return g_strdup(ms->ram_memdev_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_memdev(Object *obj, const char *value, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
g_free(ms->ram_memdev_id);
|
|
|
|
ms->ram_memdev_id = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-25 16:16:05 +01:00
|
|
|
static void machine_init_notify(Notifier *notifier, void *data)
|
|
|
|
{
|
|
|
|
MachineState *machine = MACHINE(qdev_get_machine());
|
2014-07-01 16:14:41 +02:00
|
|
|
|
|
|
|
/*
|
2017-11-25 16:16:05 +01:00
|
|
|
* Loop through all dynamically created sysbus devices and check if they are
|
|
|
|
* all allowed. If a device is not allowed, error out.
|
2014-07-01 16:14:41 +02:00
|
|
|
*/
|
2017-11-25 16:16:05 +01:00
|
|
|
foreach_dynamic_sysbus_device(validate_sysbus_device, machine);
|
2014-07-01 16:14:41 +02:00
|
|
|
}
|
|
|
|
|
2017-02-09 12:08:38 +01:00
|
|
|
HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
HotpluggableCPUList *head = NULL;
|
2018-01-10 16:22:50 +01:00
|
|
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
|
|
|
|
|
|
|
/* force board to initialize possible_cpus if it hasn't been done yet */
|
|
|
|
mc->possible_cpu_arch_ids(machine);
|
2017-02-09 12:08:38 +01:00
|
|
|
|
|
|
|
for (i = 0; i < machine->possible_cpus->len; i++) {
|
2018-01-10 16:22:50 +01:00
|
|
|
Object *cpu;
|
2017-02-09 12:08:38 +01:00
|
|
|
HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1);
|
|
|
|
|
2018-01-10 16:22:50 +01:00
|
|
|
cpu_item->type = g_strdup(machine->possible_cpus->cpus[i].type);
|
2017-02-09 12:08:38 +01:00
|
|
|
cpu_item->vcpus_count = machine->possible_cpus->cpus[i].vcpus_count;
|
|
|
|
cpu_item->props = g_memdup(&machine->possible_cpus->cpus[i].props,
|
|
|
|
sizeof(*cpu_item->props));
|
|
|
|
|
|
|
|
cpu = machine->possible_cpus->cpus[i].cpu;
|
|
|
|
if (cpu) {
|
|
|
|
cpu_item->has_qom_path = true;
|
|
|
|
cpu_item->qom_path = object_get_canonical_path(cpu);
|
|
|
|
}
|
2020-11-13 02:13:37 +01:00
|
|
|
QAPI_LIST_PREPEND(head, cpu_item);
|
2017-02-09 12:08:38 +01:00
|
|
|
}
|
|
|
|
return head;
|
|
|
|
}
|
|
|
|
|
2017-05-10 13:29:50 +02:00
|
|
|
/**
|
|
|
|
* machine_set_cpu_numa_node:
|
|
|
|
* @machine: machine object to modify
|
|
|
|
* @props: specifies which cpu objects to assign to
|
|
|
|
* numa node specified by @props.node_id
|
|
|
|
* @errp: if an error occurs, a pointer to an area to store the error
|
|
|
|
*
|
|
|
|
* Associate NUMA node specified by @props.node_id with cpu slots that
|
|
|
|
* match socket/core/thread-ids specified by @props. It's recommended to use
|
|
|
|
* query-hotpluggable-cpus.props values to specify affected cpu slots,
|
|
|
|
* which would lead to exact 1:1 mapping of cpu slots to NUMA node.
|
|
|
|
*
|
|
|
|
* However for CLI convenience it's possible to pass in subset of properties,
|
|
|
|
* which would affect all cpu slots that match it.
|
|
|
|
* Ex for pc machine:
|
|
|
|
* -smp 4,cores=2,sockets=2 -numa node,nodeid=0 -numa node,nodeid=1 \
|
|
|
|
* -numa cpu,node-id=0,socket_id=0 \
|
|
|
|
* -numa cpu,node-id=1,socket_id=1
|
|
|
|
* will assign all child cores of socket 0 to node 0 and
|
|
|
|
* of socket 1 to node 1.
|
|
|
|
*
|
|
|
|
* On attempt of reassigning (already assigned) cpu slot to another NUMA node,
|
|
|
|
* return error.
|
|
|
|
* Empty subset is disallowed and function will return with error in this case.
|
|
|
|
*/
|
|
|
|
void machine_set_cpu_numa_node(MachineState *machine,
|
|
|
|
const CpuInstanceProperties *props, Error **errp)
|
|
|
|
{
|
|
|
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
2019-12-13 02:19:22 +01:00
|
|
|
NodeInfo *numa_info = machine->numa_state->nodes;
|
2017-05-10 13:29:50 +02:00
|
|
|
bool match = false;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!mc->possible_cpu_arch_ids) {
|
|
|
|
error_setg(errp, "mapping of CPUs to NUMA node is not supported");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* disabling node mapping is not supported, forbid it */
|
|
|
|
assert(props->has_node_id);
|
|
|
|
|
|
|
|
/* force board to initialize possible_cpus if it hasn't been done yet */
|
|
|
|
mc->possible_cpu_arch_ids(machine);
|
|
|
|
|
|
|
|
for (i = 0; i < machine->possible_cpus->len; i++) {
|
|
|
|
CPUArchId *slot = &machine->possible_cpus->cpus[i];
|
|
|
|
|
|
|
|
/* reject unsupported by board properties */
|
|
|
|
if (props->has_thread_id && !slot->props.has_thread_id) {
|
|
|
|
error_setg(errp, "thread-id is not supported");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (props->has_core_id && !slot->props.has_core_id) {
|
|
|
|
error_setg(errp, "core-id is not supported");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (props->has_socket_id && !slot->props.has_socket_id) {
|
|
|
|
error_setg(errp, "socket-id is not supported");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-06-12 10:40:58 +02:00
|
|
|
if (props->has_die_id && !slot->props.has_die_id) {
|
|
|
|
error_setg(errp, "die-id is not supported");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-10 13:29:50 +02:00
|
|
|
/* skip slots with explicit mismatch */
|
|
|
|
if (props->has_thread_id && props->thread_id != slot->props.thread_id) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (props->has_core_id && props->core_id != slot->props.core_id) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-06-12 10:40:58 +02:00
|
|
|
if (props->has_die_id && props->die_id != slot->props.die_id) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-05-10 13:29:50 +02:00
|
|
|
if (props->has_socket_id && props->socket_id != slot->props.socket_id) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reject assignment if slot is already assigned, for compatibility
|
|
|
|
* of legacy cpu_index mapping with SPAPR core based mapping do not
|
|
|
|
* error out if cpu thread and matched core have the same node-id */
|
|
|
|
if (slot->props.has_node_id &&
|
|
|
|
slot->props.node_id != props->node_id) {
|
|
|
|
error_setg(errp, "CPU is already assigned to node-id: %" PRId64,
|
|
|
|
slot->props.node_id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* assign slot to node as it's matched '-numa cpu' key */
|
|
|
|
match = true;
|
|
|
|
slot->props.node_id = props->node_id;
|
|
|
|
slot->props.has_node_id = props->has_node_id;
|
2019-12-13 02:19:22 +01:00
|
|
|
|
|
|
|
if (machine->numa_state->hmat_enabled) {
|
|
|
|
if ((numa_info[props->node_id].initiator < MAX_NODES) &&
|
|
|
|
(props->node_id != numa_info[props->node_id].initiator)) {
|
|
|
|
error_setg(errp, "The initiator of CPU NUMA node %" PRId64
|
|
|
|
" should be itself", props->node_id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
numa_info[props->node_id].has_cpu = true;
|
|
|
|
numa_info[props->node_id].initiator = props->node_id;
|
|
|
|
}
|
2017-05-10 13:29:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!match) {
|
|
|
|
error_setg(errp, "no match found");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-20 07:45:24 +02:00
|
|
|
static void smp_parse(MachineState *ms, QemuOpts *opts)
|
|
|
|
{
|
|
|
|
if (opts) {
|
|
|
|
unsigned cpus = qemu_opt_get_number(opts, "cpus", 0);
|
|
|
|
unsigned sockets = qemu_opt_get_number(opts, "sockets", 0);
|
|
|
|
unsigned cores = qemu_opt_get_number(opts, "cores", 0);
|
|
|
|
unsigned threads = qemu_opt_get_number(opts, "threads", 0);
|
|
|
|
|
|
|
|
/* compute missing values, prefer sockets over cores over threads */
|
|
|
|
if (cpus == 0 || sockets == 0) {
|
|
|
|
cores = cores > 0 ? cores : 1;
|
|
|
|
threads = threads > 0 ? threads : 1;
|
|
|
|
if (cpus == 0) {
|
|
|
|
sockets = sockets > 0 ? sockets : 1;
|
|
|
|
cpus = cores * threads * sockets;
|
|
|
|
} else {
|
|
|
|
ms->smp.max_cpus =
|
|
|
|
qemu_opt_get_number(opts, "maxcpus", cpus);
|
|
|
|
sockets = ms->smp.max_cpus / (cores * threads);
|
|
|
|
}
|
|
|
|
} else if (cores == 0) {
|
|
|
|
threads = threads > 0 ? threads : 1;
|
|
|
|
cores = cpus / (sockets * threads);
|
|
|
|
cores = cores > 0 ? cores : 1;
|
|
|
|
} else if (threads == 0) {
|
|
|
|
threads = cpus / (cores * sockets);
|
|
|
|
threads = threads > 0 ? threads : 1;
|
|
|
|
} else if (sockets * cores * threads < cpus) {
|
|
|
|
error_report("cpu topology: "
|
|
|
|
"sockets (%u) * cores (%u) * threads (%u) < "
|
|
|
|
"smp_cpus (%u)",
|
|
|
|
sockets, cores, threads, cpus);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
ms->smp.max_cpus =
|
|
|
|
qemu_opt_get_number(opts, "maxcpus", cpus);
|
|
|
|
|
|
|
|
if (ms->smp.max_cpus < cpus) {
|
|
|
|
error_report("maxcpus must be equal to or greater than smp");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2020-09-11 15:32:02 +02:00
|
|
|
if (sockets * cores * threads != ms->smp.max_cpus) {
|
|
|
|
error_report("Invalid CPU topology: "
|
|
|
|
"sockets (%u) * cores (%u) * threads (%u) "
|
|
|
|
"!= maxcpus (%u)",
|
2019-06-20 07:45:24 +02:00
|
|
|
sockets, cores, threads,
|
|
|
|
ms->smp.max_cpus);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
ms->smp.cpus = cpus;
|
|
|
|
ms->smp.cores = cores;
|
|
|
|
ms->smp.threads = threads;
|
2020-03-11 23:53:06 +01:00
|
|
|
ms->smp.sockets = sockets;
|
2019-06-20 07:45:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ms->smp.cpus > 1) {
|
|
|
|
Error *blocker = NULL;
|
|
|
|
error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp");
|
|
|
|
replay_add_blocker(blocker);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-07 07:33:57 +02:00
|
|
|
static void machine_class_init(ObjectClass *oc, void *data)
|
|
|
|
{
|
|
|
|
MachineClass *mc = MACHINE_CLASS(oc);
|
|
|
|
|
|
|
|
/* Default 128 MB as guest ram size */
|
2018-06-25 14:41:57 +02:00
|
|
|
mc->default_ram_size = 128 * MiB;
|
2015-12-01 23:58:08 +01:00
|
|
|
mc->rom_file_has_mr = true;
|
2019-06-20 07:45:24 +02:00
|
|
|
mc->smp_parse = smp_parse;
|
2016-10-13 22:40:46 +02:00
|
|
|
|
2017-03-21 11:25:42 +01:00
|
|
|
/* numa node memory size aligned on 8MB by default.
|
|
|
|
* On Linux, each node's border has to be 8MB aligned
|
|
|
|
*/
|
|
|
|
mc->numa_mem_align_shift = 23;
|
|
|
|
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_add_str(oc, "kernel",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_kernel, machine_set_kernel);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "kernel",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Linux kernel image file");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
|
|
|
object_class_property_add_str(oc, "initrd",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_initrd, machine_set_initrd);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "initrd",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Linux initial ramdisk file");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
|
|
|
object_class_property_add_str(oc, "append",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_append, machine_set_append);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "append",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Linux kernel command line");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
|
|
|
object_class_property_add_str(oc, "dtb",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_dtb, machine_set_dtb);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "dtb",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Linux kernel device tree file");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
|
|
|
object_class_property_add_str(oc, "dumpdtb",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_dumpdtb, machine_set_dumpdtb);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "dumpdtb",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Dump current dtb to a file and quit");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
|
|
|
object_class_property_add(oc, "phandle-start", "int",
|
|
|
|
machine_get_phandle_start, machine_set_phandle_start,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
NULL, NULL);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "phandle-start",
|
2020-05-05 17:29:15 +02:00
|
|
|
"The first phandle ID we may generate dynamically");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
|
|
|
object_class_property_add_str(oc, "dt-compatible",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_dt_compatible, machine_set_dt_compatible);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "dt-compatible",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Overrides the \"compatible\" property of the dt root node");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
|
|
|
object_class_property_add_bool(oc, "dump-guest-core",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_dump_guest_core, machine_set_dump_guest_core);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "dump-guest-core",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Include guest memory in a core dump");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
|
|
|
object_class_property_add_bool(oc, "mem-merge",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_mem_merge, machine_set_mem_merge);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "mem-merge",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Enable/disable memory merge support");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
|
|
|
object_class_property_add_bool(oc, "usb",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_usb, machine_set_usb);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "usb",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Set on/off to enable/disable usb");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
|
|
|
object_class_property_add_bool(oc, "graphics",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_graphics, machine_set_graphics);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "graphics",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Set on/off to enable/disable graphics emulation");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
|
|
|
object_class_property_add_str(oc, "firmware",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_firmware, machine_set_firmware);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "firmware",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Firmware image");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
|
|
|
object_class_property_add_bool(oc, "suppress-vmdesc",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_suppress_vmdesc, machine_set_suppress_vmdesc);
|
2016-10-13 22:40:46 +02:00
|
|
|
object_class_property_set_description(oc, "suppress-vmdesc",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Set on to disable self-describing migration");
|
2016-10-13 22:40:46 +02:00
|
|
|
|
2018-03-08 13:48:38 +01:00
|
|
|
object_class_property_add_str(oc, "memory-encryption",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_memory_encryption, machine_set_memory_encryption);
|
2018-03-08 13:48:38 +01:00
|
|
|
object_class_property_set_description(oc, "memory-encryption",
|
2020-05-05 17:29:15 +02:00
|
|
|
"Set memory encryption object to use");
|
2020-09-22 00:10:41 +02:00
|
|
|
|
|
|
|
object_class_property_add_str(oc, "memory-backend",
|
|
|
|
machine_get_memdev, machine_set_memdev);
|
|
|
|
object_class_property_set_description(oc, "memory-backend",
|
|
|
|
"Set RAM backend"
|
|
|
|
"Valid value is ID of hostmem based backend");
|
2015-05-07 07:33:57 +02:00
|
|
|
}
|
|
|
|
|
2015-08-20 23:54:35 +02:00
|
|
|
static void machine_class_base_init(ObjectClass *oc, void *data)
|
|
|
|
{
|
2020-10-21 13:23:49 +02:00
|
|
|
MachineClass *mc = MACHINE_CLASS(oc);
|
|
|
|
mc->max_cpus = mc->max_cpus ?: 1;
|
|
|
|
mc->min_cpus = mc->min_cpus ?: 1;
|
|
|
|
mc->default_cpus = mc->default_cpus ?: 1;
|
|
|
|
|
2015-08-20 23:54:35 +02:00
|
|
|
if (!object_class_is_abstract(oc)) {
|
|
|
|
const char *cname = object_class_get_name(oc);
|
|
|
|
assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX));
|
2015-08-20 23:54:36 +02:00
|
|
|
mc->name = g_strndup(cname,
|
|
|
|
strlen(cname) - strlen(TYPE_MACHINE_SUFFIX));
|
2018-12-01 20:44:11 +01:00
|
|
|
mc->compat_props = g_ptr_array_new();
|
2015-08-20 23:54:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-26 14:40:58 +02:00
|
|
|
static void machine_initfn(Object *obj)
|
|
|
|
{
|
2014-07-01 16:14:41 +02:00
|
|
|
MachineState *ms = MACHINE(obj);
|
2018-12-20 06:40:35 +01:00
|
|
|
MachineClass *mc = MACHINE_GET_CLASS(obj);
|
2014-07-01 16:14:41 +02:00
|
|
|
|
2020-10-21 11:25:58 +02:00
|
|
|
container_get(obj, "/peripheral");
|
|
|
|
container_get(obj, "/peripheral-anon");
|
|
|
|
|
2015-02-04 16:43:54 +01:00
|
|
|
ms->dump_guest_core = true;
|
2015-02-04 16:43:55 +01:00
|
|
|
ms->mem_merge = true;
|
2016-04-19 21:55:25 +02:00
|
|
|
ms->enable_graphics = true;
|
2020-11-03 09:45:26 +01:00
|
|
|
ms->kernel_cmdline = g_strdup("");
|
2015-02-04 16:43:49 +01:00
|
|
|
|
2019-03-08 19:20:53 +01:00
|
|
|
if (mc->nvdimm_supported) {
|
|
|
|
Object *obj = OBJECT(ms);
|
|
|
|
|
|
|
|
ms->nvdimms_state = g_new0(NVDIMMState, 1);
|
|
|
|
object_property_add_bool(obj, "nvdimm",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_nvdimm, machine_set_nvdimm);
|
2019-03-08 19:20:53 +01:00
|
|
|
object_property_set_description(obj, "nvdimm",
|
|
|
|
"Set on/off to enable/disable "
|
2020-05-05 17:29:15 +02:00
|
|
|
"NVDIMM instantiation");
|
2019-03-08 19:20:53 +01:00
|
|
|
|
|
|
|
object_property_add_str(obj, "nvdimm-persistence",
|
|
|
|
machine_get_nvdimm_persistence,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_set_nvdimm_persistence);
|
2019-03-08 19:20:53 +01:00
|
|
|
object_property_set_description(obj, "nvdimm-persistence",
|
|
|
|
"Set NVDIMM persistence"
|
2020-05-05 17:29:15 +02:00
|
|
|
"Valid values are cpu, mem-ctrl");
|
2019-03-08 19:20:53 +01:00
|
|
|
}
|
|
|
|
|
2019-12-12 13:48:56 +01:00
|
|
|
if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) {
|
2019-08-09 08:57:22 +02:00
|
|
|
ms->numa_state = g_new0(NumaState, 1);
|
2019-12-13 02:19:22 +01:00
|
|
|
object_property_add_bool(obj, "hmat",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
machine_get_hmat, machine_set_hmat);
|
2019-12-13 02:19:22 +01:00
|
|
|
object_property_set_description(obj, "hmat",
|
|
|
|
"Set on/off to enable/disable "
|
|
|
|
"ACPI Heterogeneous Memory Attribute "
|
2020-05-05 17:29:15 +02:00
|
|
|
"Table (HMAT)");
|
2019-08-09 08:57:22 +02:00
|
|
|
}
|
2019-03-08 19:20:53 +01:00
|
|
|
|
2014-07-01 16:14:41 +02:00
|
|
|
/* Register notifier when init is done for sysbus sanity checks */
|
|
|
|
ms->sysbus_notifier.notify = machine_init_notify;
|
|
|
|
qemu_add_machine_init_done_notifier(&ms->sysbus_notifier);
|
2020-10-21 12:45:14 +02:00
|
|
|
|
|
|
|
/* default to mc->default_cpus */
|
|
|
|
ms->smp.cpus = mc->default_cpus;
|
|
|
|
ms->smp.max_cpus = mc->default_cpus;
|
|
|
|
ms->smp.cores = 1;
|
|
|
|
ms->smp.threads = 1;
|
|
|
|
ms->smp.sockets = 1;
|
2014-05-26 14:40:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_finalize(Object *obj)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
g_free(ms->kernel_filename);
|
|
|
|
g_free(ms->initrd_filename);
|
|
|
|
g_free(ms->kernel_cmdline);
|
|
|
|
g_free(ms->dtb);
|
|
|
|
g_free(ms->dumpdtb);
|
|
|
|
g_free(ms->dt_compatible);
|
|
|
|
g_free(ms->firmware);
|
2018-07-02 11:41:52 +02:00
|
|
|
g_free(ms->device_memory);
|
2019-03-08 19:20:53 +01:00
|
|
|
g_free(ms->nvdimms_state);
|
2019-08-09 08:57:22 +02:00
|
|
|
g_free(ms->numa_state);
|
2014-05-26 14:40:58 +02:00
|
|
|
}
|
2014-03-05 18:30:45 +01:00
|
|
|
|
2015-01-06 14:29:13 +01:00
|
|
|
bool machine_usb(MachineState *machine)
|
|
|
|
{
|
|
|
|
return machine->usb;
|
|
|
|
}
|
|
|
|
|
2015-02-04 16:43:53 +01:00
|
|
|
int machine_phandle_start(MachineState *machine)
|
|
|
|
{
|
|
|
|
return machine->phandle_start;
|
|
|
|
}
|
|
|
|
|
2015-02-04 16:43:54 +01:00
|
|
|
bool machine_dump_guest_core(MachineState *machine)
|
|
|
|
{
|
|
|
|
return machine->dump_guest_core;
|
|
|
|
}
|
|
|
|
|
2015-02-04 16:43:55 +01:00
|
|
|
bool machine_mem_merge(MachineState *machine)
|
|
|
|
{
|
|
|
|
return machine->mem_merge;
|
|
|
|
}
|
|
|
|
|
2017-05-10 13:29:59 +02:00
|
|
|
static char *cpu_slot_to_string(const CPUArchId *cpu)
|
|
|
|
{
|
|
|
|
GString *s = g_string_new(NULL);
|
|
|
|
if (cpu->props.has_socket_id) {
|
|
|
|
g_string_append_printf(s, "socket-id: %"PRId64, cpu->props.socket_id);
|
|
|
|
}
|
2019-06-12 10:40:58 +02:00
|
|
|
if (cpu->props.has_die_id) {
|
|
|
|
g_string_append_printf(s, "die-id: %"PRId64, cpu->props.die_id);
|
|
|
|
}
|
2017-05-10 13:29:59 +02:00
|
|
|
if (cpu->props.has_core_id) {
|
|
|
|
if (s->len) {
|
|
|
|
g_string_append_printf(s, ", ");
|
|
|
|
}
|
|
|
|
g_string_append_printf(s, "core-id: %"PRId64, cpu->props.core_id);
|
|
|
|
}
|
|
|
|
if (cpu->props.has_thread_id) {
|
|
|
|
if (s->len) {
|
|
|
|
g_string_append_printf(s, ", ");
|
|
|
|
}
|
|
|
|
g_string_append_printf(s, "thread-id: %"PRId64, cpu->props.thread_id);
|
|
|
|
}
|
|
|
|
return g_string_free(s, false);
|
|
|
|
}
|
|
|
|
|
2019-12-13 02:19:22 +01:00
|
|
|
static void numa_validate_initiator(NumaState *numa_state)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
NodeInfo *numa_info = numa_state->nodes;
|
|
|
|
|
|
|
|
for (i = 0; i < numa_state->num_nodes; i++) {
|
|
|
|
if (numa_info[i].initiator == MAX_NODES) {
|
|
|
|
error_report("The initiator of NUMA node %d is missing, use "
|
|
|
|
"'-numa node,initiator' option to declare it", i);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!numa_info[numa_info[i].initiator].present) {
|
|
|
|
error_report("NUMA node %" PRIu16 " is missing, use "
|
|
|
|
"'-numa node' option to declare it first",
|
|
|
|
numa_info[i].initiator);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!numa_info[numa_info[i].initiator].has_cpu) {
|
|
|
|
error_report("The initiator of NUMA node %d is invalid", i);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-04 10:37:39 +02:00
|
|
|
static void machine_numa_finish_cpu_init(MachineState *machine)
|
2017-05-10 13:29:59 +02:00
|
|
|
{
|
|
|
|
int i;
|
2017-05-30 18:23:57 +02:00
|
|
|
bool default_mapping;
|
2017-05-10 13:29:59 +02:00
|
|
|
GString *s = g_string_new(NULL);
|
|
|
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
|
|
|
const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(machine);
|
|
|
|
|
2019-08-09 08:57:22 +02:00
|
|
|
assert(machine->numa_state->num_nodes);
|
2017-05-30 18:23:57 +02:00
|
|
|
for (i = 0; i < possible_cpus->len; i++) {
|
|
|
|
if (possible_cpus->cpus[i].props.has_node_id) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default_mapping = (i == possible_cpus->len);
|
|
|
|
|
2017-05-10 13:29:59 +02:00
|
|
|
for (i = 0; i < possible_cpus->len; i++) {
|
|
|
|
const CPUArchId *cpu_slot = &possible_cpus->cpus[i];
|
|
|
|
|
|
|
|
if (!cpu_slot->props.has_node_id) {
|
2017-05-30 18:23:58 +02:00
|
|
|
/* fetch default mapping from board and enable it */
|
|
|
|
CpuInstanceProperties props = cpu_slot->props;
|
|
|
|
|
2017-06-01 12:53:28 +02:00
|
|
|
props.node_id = mc->get_default_cpu_node_id(machine, i);
|
2017-05-30 18:23:58 +02:00
|
|
|
if (!default_mapping) {
|
2017-05-30 18:23:57 +02:00
|
|
|
/* record slots with not set mapping,
|
|
|
|
* TODO: make it hard error in future */
|
|
|
|
char *cpu_str = cpu_slot_to_string(cpu_slot);
|
|
|
|
g_string_append_printf(s, "%sCPU %d [%s]",
|
|
|
|
s->len ? ", " : "", i, cpu_str);
|
|
|
|
g_free(cpu_str);
|
2017-05-30 18:23:58 +02:00
|
|
|
|
|
|
|
/* non mapped cpus used to fallback to node 0 */
|
|
|
|
props.node_id = 0;
|
2017-05-30 18:23:57 +02:00
|
|
|
}
|
2017-05-30 18:23:58 +02:00
|
|
|
|
|
|
|
props.has_node_id = true;
|
|
|
|
machine_set_cpu_numa_node(machine, &props, &error_fatal);
|
2017-05-10 13:29:59 +02:00
|
|
|
}
|
|
|
|
}
|
2019-12-13 02:19:22 +01:00
|
|
|
|
|
|
|
if (machine->numa_state->hmat_enabled) {
|
|
|
|
numa_validate_initiator(machine->numa_state);
|
|
|
|
}
|
|
|
|
|
2017-05-18 10:09:31 +02:00
|
|
|
if (s->len && !qtest_enabled()) {
|
2017-07-12 15:57:41 +02:00
|
|
|
warn_report("CPU(s) not present in any NUMA nodes: %s",
|
|
|
|
s->str);
|
|
|
|
warn_report("All CPU(s) up to maxcpus should be described "
|
|
|
|
"in NUMA config, ability to start up with partial NUMA "
|
|
|
|
"mappings is obsoleted and will be removed in future");
|
2017-05-10 13:29:59 +02:00
|
|
|
}
|
|
|
|
g_string_free(s, true);
|
|
|
|
}
|
|
|
|
|
2020-02-19 17:08:38 +01:00
|
|
|
MemoryRegion *machine_consume_memdev(MachineState *machine,
|
|
|
|
HostMemoryBackend *backend)
|
|
|
|
{
|
|
|
|
MemoryRegion *ret = host_memory_backend_get_memory(backend);
|
|
|
|
|
|
|
|
if (memory_region_is_mapped(ret)) {
|
2020-07-14 18:02:00 +02:00
|
|
|
error_report("memory backend %s can't be used multiple times.",
|
|
|
|
object_get_canonical_path_component(OBJECT(backend)));
|
2020-02-19 17:08:38 +01:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
host_memory_backend_set_mapped(backend, true);
|
|
|
|
vmstate_register_ram_global(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-10-21 12:49:31 +02:00
|
|
|
bool machine_smp_parse(MachineState *ms, QemuOpts *opts, Error **errp)
|
|
|
|
{
|
|
|
|
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
|
|
|
|
|
|
|
mc->smp_parse(ms, opts);
|
|
|
|
|
|
|
|
/* sanity-check smp_cpus and max_cpus against mc */
|
|
|
|
if (ms->smp.cpus < mc->min_cpus) {
|
|
|
|
error_setg(errp, "Invalid SMP CPUs %d. The min CPUs "
|
|
|
|
"supported by machine '%s' is %d",
|
|
|
|
ms->smp.cpus,
|
|
|
|
mc->name, mc->min_cpus);
|
|
|
|
return false;
|
|
|
|
} else if (ms->smp.max_cpus > mc->max_cpus) {
|
|
|
|
error_setg(errp, "Invalid SMP CPUs %d. The max CPUs "
|
|
|
|
"supported by machine '%s' is %d",
|
|
|
|
current_machine->smp.max_cpus,
|
|
|
|
mc->name, mc->max_cpus);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-05-10 13:29:58 +02:00
|
|
|
void machine_run_board_init(MachineState *machine)
|
|
|
|
{
|
|
|
|
MachineClass *machine_class = MACHINE_GET_CLASS(machine);
|
2020-09-22 09:14:14 +02:00
|
|
|
ObjectClass *oc = object_class_by_name(machine->cpu_type);
|
|
|
|
CPUClass *cc;
|
2017-05-10 13:29:59 +02:00
|
|
|
|
2020-10-21 13:19:34 +02:00
|
|
|
/* This checkpoint is required by replay to separate prior clock
|
|
|
|
reading from the other reads, because timer polling functions query
|
|
|
|
clock values from the log. */
|
|
|
|
replay_checkpoint(CHECKPOINT_INIT);
|
|
|
|
|
2020-02-19 17:08:38 +01:00
|
|
|
if (machine->ram_memdev_id) {
|
|
|
|
Object *o;
|
|
|
|
o = object_resolve_path_type(machine->ram_memdev_id,
|
|
|
|
TYPE_MEMORY_BACKEND, NULL);
|
|
|
|
machine->ram = machine_consume_memdev(machine, MEMORY_BACKEND(o));
|
|
|
|
}
|
|
|
|
|
2019-12-12 13:48:56 +01:00
|
|
|
if (machine->numa_state) {
|
2019-08-09 08:57:22 +02:00
|
|
|
numa_complete_configuration(machine);
|
|
|
|
if (machine->numa_state->num_nodes) {
|
|
|
|
machine_numa_finish_cpu_init(machine);
|
|
|
|
}
|
2018-07-10 12:51:29 +02:00
|
|
|
}
|
2017-10-03 22:05:09 +02:00
|
|
|
|
|
|
|
/* If the machine supports the valid_cpu_types check and the user
|
|
|
|
* specified a CPU with -cpu check here that the user CPU is supported.
|
|
|
|
*/
|
|
|
|
if (machine_class->valid_cpu_types && machine->cpu_type) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; machine_class->valid_cpu_types[i]; i++) {
|
2020-09-22 09:14:14 +02:00
|
|
|
if (object_class_dynamic_cast(oc,
|
2017-10-03 22:05:09 +02:00
|
|
|
machine_class->valid_cpu_types[i])) {
|
|
|
|
/* The user specificed CPU is in the valid field, we are
|
|
|
|
* good to go.
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!machine_class->valid_cpu_types[i]) {
|
|
|
|
/* The user specified CPU is not valid */
|
|
|
|
error_report("Invalid CPU type: %s", machine->cpu_type);
|
|
|
|
error_printf("The valid types are: %s",
|
|
|
|
machine_class->valid_cpu_types[0]);
|
|
|
|
for (i = 1; machine_class->valid_cpu_types[i]; i++) {
|
|
|
|
error_printf(", %s", machine_class->valid_cpu_types[i]);
|
|
|
|
}
|
|
|
|
error_printf("\n");
|
|
|
|
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-22 09:14:14 +02:00
|
|
|
/* Check if CPU type is deprecated and warn if so */
|
|
|
|
cc = CPU_CLASS(oc);
|
|
|
|
if (cc && cc->deprecation_note) {
|
|
|
|
warn_report("CPU model %s is deprecated -- %s", machine->cpu_type,
|
|
|
|
cc->deprecation_note);
|
|
|
|
}
|
|
|
|
|
2017-05-10 13:29:58 +02:00
|
|
|
machine_class->init(machine);
|
2020-11-12 15:38:36 +01:00
|
|
|
phase_advance(PHASE_MACHINE_INITIALIZED);
|
2017-05-10 13:29:58 +02:00
|
|
|
}
|
|
|
|
|
2020-10-28 12:36:57 +01:00
|
|
|
static NotifierList machine_init_done_notifiers =
|
|
|
|
NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
|
|
|
|
|
|
|
|
void qemu_add_machine_init_done_notifier(Notifier *notify)
|
|
|
|
{
|
|
|
|
notifier_list_add(&machine_init_done_notifiers, notify);
|
2020-11-12 15:38:36 +01:00
|
|
|
if (phase_check(PHASE_MACHINE_READY)) {
|
2020-10-28 12:36:57 +01:00
|
|
|
notify->notify(notify, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void qemu_remove_machine_init_done_notifier(Notifier *notify)
|
|
|
|
{
|
|
|
|
notifier_remove(notify);
|
|
|
|
}
|
|
|
|
|
2020-11-13 08:43:56 +01:00
|
|
|
void qdev_machine_creation_done(void)
|
2020-10-28 12:36:57 +01:00
|
|
|
{
|
2020-11-13 08:43:56 +01:00
|
|
|
cpu_synchronize_all_post_init();
|
|
|
|
|
|
|
|
if (current_machine->boot_once) {
|
|
|
|
qemu_boot_set(current_machine->boot_once, &error_fatal);
|
|
|
|
qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ok, initial machine setup is done, starting from now we can
|
|
|
|
* only create hotpluggable devices
|
|
|
|
*/
|
2020-11-12 15:38:36 +01:00
|
|
|
phase_advance(PHASE_MACHINE_READY);
|
2020-11-13 08:43:56 +01:00
|
|
|
qdev_assert_realized_properly();
|
|
|
|
|
|
|
|
/* TODO: once all bus devices are qdevified, this should be done
|
|
|
|
* when bus is created by qdev.c */
|
|
|
|
/*
|
|
|
|
* TODO: If we had a main 'reset container' that the whole system
|
|
|
|
* lived in, we could reset that using the multi-phase reset
|
|
|
|
* APIs. For the moment, we just reset the sysbus, which will cause
|
|
|
|
* all devices hanging off it (and all their child buses, recursively)
|
|
|
|
* to be reset. Note that this will *not* reset any Device objects
|
|
|
|
* which are not attached to some part of the qbus tree!
|
|
|
|
*/
|
|
|
|
qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default());
|
|
|
|
|
2020-10-28 12:36:57 +01:00
|
|
|
notifier_list_notify(&machine_init_done_notifiers, NULL);
|
2020-11-13 08:43:56 +01:00
|
|
|
|
|
|
|
if (rom_check_and_register_reset() != 0) {
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
replay_start();
|
|
|
|
|
|
|
|
/* This checkpoint is required by replay to separate prior clock
|
|
|
|
reading from the other reads, because timer polling functions query
|
|
|
|
clock values from the log. */
|
|
|
|
replay_checkpoint(CHECKPOINT_RESET);
|
|
|
|
qemu_system_reset(SHUTDOWN_CAUSE_NONE);
|
|
|
|
register_global_state();
|
2020-10-28 12:36:57 +01:00
|
|
|
}
|
|
|
|
|
2014-03-05 18:30:45 +01:00
|
|
|
static const TypeInfo machine_info = {
|
|
|
|
.name = TYPE_MACHINE,
|
|
|
|
.parent = TYPE_OBJECT,
|
|
|
|
.abstract = true,
|
|
|
|
.class_size = sizeof(MachineClass),
|
2015-05-07 07:33:57 +02:00
|
|
|
.class_init = machine_class_init,
|
2015-08-20 23:54:35 +02:00
|
|
|
.class_base_init = machine_class_base_init,
|
2014-03-05 18:30:45 +01:00
|
|
|
.instance_size = sizeof(MachineState),
|
2014-05-26 14:40:58 +02:00
|
|
|
.instance_init = machine_initfn,
|
|
|
|
.instance_finalize = machine_finalize,
|
2014-03-05 18:30:45 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static void machine_register_types(void)
|
|
|
|
{
|
|
|
|
type_register_static(&machine_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_init(machine_register_types)
|