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"
|
2022-11-30 14:56:41 +01:00
|
|
|
#include "qemu/accel.h"
|
2019-06-20 07:45:24 +02:00
|
|
|
#include "sysemu/replay.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"
|
2021-05-13 15:03:48 +02:00
|
|
|
#include "qapi/qapi-visit-machine.h"
|
2022-04-14 18:53:00 +02:00
|
|
|
#include "qom/object_interfaces.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"
|
2022-04-14 18:53:00 +02:00
|
|
|
#include "sysemu/xen.h"
|
2017-05-18 10:09:31 +02:00
|
|
|
#include "sysemu/qtest.h"
|
2023-08-29 22:14:29 +02:00
|
|
|
#include "hw/pci/pci_bridge.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-12-04 02:51:51 +01:00
|
|
|
#include "exec/confidential-guest-support.h"
|
2020-06-04 06:20:24 +02:00
|
|
|
#include "hw/virtio/virtio-pci.h"
|
2023-08-01 00:31:48 +02:00
|
|
|
#include "hw/virtio/virtio-net.h"
|
2022-04-25 10:21:50 +02:00
|
|
|
#include "audio/audio.h"
|
2014-05-26 14:40:58 +02:00
|
|
|
|
2023-08-29 22:14:29 +02:00
|
|
|
GlobalProperty hw_compat_8_1[] = {
|
|
|
|
{ TYPE_PCI_BRIDGE, "x-pci-express-writeable-slt-bug", "true" },
|
|
|
|
};
|
2023-07-18 16:22:35 +02:00
|
|
|
const size_t hw_compat_8_1_len = G_N_ELEMENTS(hw_compat_8_1);
|
|
|
|
|
2022-06-21 12:13:14 +02:00
|
|
|
GlobalProperty hw_compat_8_0[] = {
|
|
|
|
{ "migration", "multifd-flush-after-each-section", "on"},
|
2023-07-10 17:38:36 +02:00
|
|
|
{ TYPE_PCI_DEVICE, "x-pcie-ari-nextfn-1", "on" },
|
2023-08-01 00:31:48 +02:00
|
|
|
{ TYPE_VIRTIO_NET, "host_uso", "off"},
|
|
|
|
{ TYPE_VIRTIO_NET, "guest_uso4", "off"},
|
|
|
|
{ TYPE_VIRTIO_NET, "guest_uso6", "off"},
|
2022-06-21 12:13:14 +02:00
|
|
|
};
|
2023-03-14 18:30:09 +01:00
|
|
|
const size_t hw_compat_8_0_len = G_N_ELEMENTS(hw_compat_8_0);
|
|
|
|
|
2023-01-17 12:22:48 +01:00
|
|
|
GlobalProperty hw_compat_7_2[] = {
|
2023-02-23 11:20:18 +01:00
|
|
|
{ "e1000e", "migrate-timadj", "off" },
|
2023-01-17 12:22:48 +01:00
|
|
|
{ "virtio-mem", "x-early-migration", "false" },
|
2023-03-26 19:25:39 +02:00
|
|
|
{ "migration", "x-preempt-pre-7-2", "true" },
|
2023-05-03 02:27:02 +02:00
|
|
|
{ TYPE_PCI_DEVICE, "x-pcie-err-unc-mask", "off" },
|
2023-01-17 12:22:48 +01:00
|
|
|
};
|
2022-12-12 16:21:44 +01:00
|
|
|
const size_t hw_compat_7_2_len = G_N_ELEMENTS(hw_compat_7_2);
|
|
|
|
|
2022-10-17 11:25:47 +02:00
|
|
|
GlobalProperty hw_compat_7_1[] = {
|
|
|
|
{ "virtio-device", "queue_reset", "false" },
|
2023-01-09 11:58:09 +01:00
|
|
|
{ "virtio-rng-pci", "vectors", "0" },
|
2023-02-07 18:49:44 +01:00
|
|
|
{ "virtio-rng-pci-transitional", "vectors", "0" },
|
|
|
|
{ "virtio-rng-pci-non-transitional", "vectors", "0" },
|
2022-10-17 11:25:47 +02:00
|
|
|
};
|
2022-07-27 14:17:55 +02:00
|
|
|
const size_t hw_compat_7_1_len = G_N_ELEMENTS(hw_compat_7_1);
|
|
|
|
|
2022-05-12 17:14:56 +02:00
|
|
|
GlobalProperty hw_compat_7_0[] = {
|
|
|
|
{ "arm-gicv3-common", "force-8-bit-prio", "on" },
|
2022-04-29 10:33:33 +02:00
|
|
|
{ "nvme-ns", "eui64-default", "on"},
|
2022-05-12 17:14:56 +02:00
|
|
|
};
|
2022-03-16 15:55:21 +01:00
|
|
|
const size_t hw_compat_7_0_len = G_N_ELEMENTS(hw_compat_7_0);
|
|
|
|
|
2022-04-06 20:58:12 +02:00
|
|
|
GlobalProperty hw_compat_6_2[] = {
|
|
|
|
{ "PIIX4_PM", "x-not-migrate-acpi-index", "on"},
|
|
|
|
};
|
2021-12-17 15:39:48 +01:00
|
|
|
const size_t hw_compat_6_2_len = G_N_ELEMENTS(hw_compat_6_2);
|
|
|
|
|
2021-09-21 18:16:42 +02:00
|
|
|
GlobalProperty hw_compat_6_1[] = {
|
|
|
|
{ "vhost-user-vsock-device", "seqpacket", "off" },
|
2021-09-24 08:52:22 +02:00
|
|
|
{ "nvme-ns", "shared", "off" },
|
2021-09-21 18:16:42 +02:00
|
|
|
};
|
2021-08-31 03:54:26 +02:00
|
|
|
const size_t hw_compat_6_1_len = G_N_ELEMENTS(hw_compat_6_1);
|
|
|
|
|
2021-03-25 17:33:15 +01:00
|
|
|
GlobalProperty hw_compat_6_0[] = {
|
|
|
|
{ "gpex-pcihost", "allow-unmapped-accesses", "false" },
|
pckbd: don't update OBF flags if KBD_STAT_OBF is set
Don't update the OBF flags in the status register and the cor-
responding IRQ lines if KBD_STAT_OBF is set. Otherwise this
may change the PS/2 event type. If the guest ISR was already
scheduled, the changed event type will be rather surprising for
the guest.
This fixes a mouse event stream corruption. To reproduce the
problem start a FreeDOS 1.2 guest with -machine pc,accel=kvm
and -display gtk. The KVM in-kernel irqchip has to be enabled.
Now open a text file with edit.exe in the guest and hold down
the cursor right key and at the same time move the mouse around.
You will quickly notice erratic mouse movements and unexpected
mouse clicks.
A trace file shows the mouse event stream corruption. Guest
rip 0xce93 (f000:ce93) is the in al,0x60 instruction in the
seabios mouse ISR, guest rip 0xceca (f000:ceca) is the
in al,0x60 instruction in the seabios keyboard ISR.
qemu-system-x86-5659 [007] .... 280.971116:
tracing_mark_write: pckbd_kbd_update_irq kbd=0 aux=1
# gtk queues a mouse event
qemu-system-x86-5665 [000] .... 280.971121:
kvm_exit: reason EXTERNAL_INTERRUPT rip 0x22da info 0 800000fd
qemu-system-x86-5665 [000] d..1 280.971122:
kvm_entry: vcpu 0, rip 0x22da
qemu-system-x86-5665 [000] .... 280.971123:
kvm_exit: reason EXTERNAL_INTERRUPT rip 0x22da info 0 800000fd
qemu-system-x86-5665 [000] d..1 280.971124:
kvm_entry: vcpu 0, rip 0x22da
qemu-system-x86-5665 [000] .... 280.971126:
kvm_exit: reason IO_INSTRUCTION rip 0x110c8c info 640008 0
qemu-system-x86-5665 [000] .... 280.971176:
tracing_mark_write: pckbd_kbd_read_status 0x3d
# KBD_STAT_OBF and KBD_STAT_MOUSE_OBF set, the mouse ISR will
# read data from the PS/2 controller.
qemu-system-x86-5665 [000] d..1 280.971180:
kvm_entry: vcpu 0, rip 0x110c8d
qemu-system-x86-5665 [000] .... 280.971191:
kvm_exit: reason EXTERNAL_INTERRUPT rip 0x110c8d info 0 800000f6
qemu-system-x86-5665 [000] d..1 280.971191:
kvm_entry: vcpu 0, rip 0x110c8d
qemu-system-x86-5665 [000] .... 280.971193:
kvm_exit: reason IO_INSTRUCTION rip 0xce93 info 600048 0
# the mouse ISR wants to read data from the PS/2 controller
qemu-system-x86-5659 [007] .... 280.971231:
tracing_mark_write: pckbd_kbd_update_irq kbd=1 aux=0
qemu-system-x86-5659 [007] .... 280.971238:
tracing_mark_write: pckbd_kbd_update_irq kbd=1 aux=0
# gtk queues a keyboard event 0xe0 0x4d (key right)
qemu-system-x86-5665 [000] .... 280.971257:
tracing_mark_write: pckbd_kbd_update_irq kbd=0 aux=1
qemu-system-x86-5665 [000] .... 280.971262:
tracing_mark_write: pckbd_kbd_update_irq kbd=1 aux=0
# ps2_read_data() deasserts and reasserts the keyboard IRQ
qemu-system-x86-5665 [000] .... 280.971266:
tracing_mark_write: pckbd_kbd_read_data 0xe0 kbd
# -> the mouse ISR receives keyboard data
qemu-system-x86-5665 [000] d..1 280.971268:
kvm_entry: vcpu 0, rip 0xce95
qemu-system-x86-5665 [000] .... 280.971269:
kvm_exit: reason IO_INSTRUCTION rip 0xe828 info a00040 0
qemu-system-x86-5665 [000] .... 280.971270:
kvm_ack_irq: irqchip PIC slave pin 12
qemu-system-x86-5665 [000] d..1 280.971270:
kvm_entry: vcpu 0, rip 0xe82a
qemu-system-x86-5665 [000] .... 280.971271:
kvm_exit: reason IO_INSTRUCTION rip 0xe82a info 200040 0
qemu-system-x86-5665 [000] .... 280.971271:
kvm_ack_irq: irqchip PIC master pin 2
qemu-system-x86-5665 [000] d..1 280.971271:
kvm_entry: vcpu 0, rip 0xe82c
qemu-system-x86-5665 [000] .... 280.971272:
kvm_exit: reason PENDING_INTERRUPT rip 0x22da info 0 0
qemu-system-x86-5665 [000] d..1 280.971273:
kvm_entry: vcpu 0, rip 0x22da
qemu-system-x86-5665 [000] .... 280.971274:
kvm_exit: reason IO_INSTRUCTION rip 0x110c8c info 640008 0
qemu-system-x86-5665 [000] .... 280.971275:
tracing_mark_write: pckbd_kbd_read_status 0x1d
qemu-system-x86-5665 [000] d..1 280.971276:
kvm_entry: vcpu 0, rip 0x110c8d
qemu-system-x86-5665 [000] .... 280.971277:
kvm_exit: reason IO_INSTRUCTION rip 0xceca info 600048 0
# the keyboard ISR wants to read data from the PS/2 controller
qemu-system-x86-5665 [000] .... 280.971279:
tracing_mark_write: pckbd_kbd_update_irq kbd=0 aux=1
qemu-system-x86-5665 [000] .... 280.971282:
tracing_mark_write: pckbd_kbd_read_data 0x4d kbd
# the keyboard ISR receives the second byte of the keyboard event
Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
Message-Id: <20210525181441.27768-5-vr_qemu@t-online.de>
[ kraxel: add missing include ]
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2021-05-25 20:14:34 +02:00
|
|
|
{ "i8042", "extended-state", "false"},
|
2021-06-14 22:19:01 +02:00
|
|
|
{ "nvme-ns", "eui64-default", "off"},
|
2021-07-23 09:55:10 +02:00
|
|
|
{ "e1000", "init-vet", "off" },
|
2021-07-23 09:55:11 +02:00
|
|
|
{ "e1000e", "init-vet", "off" },
|
2021-09-21 18:16:41 +02:00
|
|
|
{ "vhost-vsock-device", "seqpacket", "off" },
|
2021-03-25 17:33:15 +01:00
|
|
|
};
|
2021-03-31 13:19:00 +02:00
|
|
|
const size_t hw_compat_6_0_len = G_N_ELEMENTS(hw_compat_6_0);
|
|
|
|
|
2021-02-18 06:51:12 +01:00
|
|
|
GlobalProperty hw_compat_5_2[] = {
|
|
|
|
{ "ICH9-LPC", "smm-compat", "on"},
|
|
|
|
{ "PIIX4_PM", "smm-compat", "on"},
|
2021-02-25 01:12:39 +01:00
|
|
|
{ "virtio-blk-device", "report-discard-granularity", "off" },
|
2021-11-03 12:38:31 +01:00
|
|
|
{ "virtio-net-pci-base", "vectors", "3"},
|
2021-02-18 06:51:12 +01:00
|
|
|
};
|
2020-11-09 18:39:28 +01:00
|
|
|
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 */
|
2021-03-18 03:38:01 +01:00
|
|
|
{ "pl011", "migrate-clk", "off" },
|
2021-04-06 06:03:30 +02:00
|
|
|
{ "virtio-pci", "x-ats-page-aligned", "off"},
|
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);
|
|
|
|
|
2020-12-04 02:51:51 +01:00
|
|
|
if (ms->cgs) {
|
|
|
|
return g_strdup(object_get_canonical_path_component(OBJECT(ms->cgs)));
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2018-03-08 13:48:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_memory_encryption(Object *obj, const char *value,
|
|
|
|
Error **errp)
|
|
|
|
{
|
2020-12-04 02:51:51 +01:00
|
|
|
Object *cgs =
|
|
|
|
object_resolve_path_component(object_get_objects_root(), value);
|
|
|
|
|
|
|
|
if (!cgs) {
|
|
|
|
error_setg(errp, "No such memory encryption object '%s'", value);
|
|
|
|
return;
|
|
|
|
}
|
2018-03-08 13:48:38 +01:00
|
|
|
|
2020-12-04 02:51:51 +01:00
|
|
|
object_property_set_link(obj, "confidential-guest-support", cgs, errp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_check_confidential_guest_support(const Object *obj,
|
|
|
|
const char *name,
|
|
|
|
Object *new_target,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* So far the only constraint is that the target has the
|
|
|
|
* TYPE_CONFIDENTIAL_GUEST_SUPPORT interface, and that's checked
|
|
|
|
* by the QOM core
|
|
|
|
*/
|
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;
|
|
|
|
}
|
|
|
|
|
2022-04-14 18:52:58 +02:00
|
|
|
static void machine_get_mem(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
MemorySizeConfiguration mem = {
|
|
|
|
.has_size = true,
|
|
|
|
.size = ms->ram_size,
|
|
|
|
.has_max_size = !!ms->ram_slots,
|
|
|
|
.max_size = ms->maxram_size,
|
|
|
|
.has_slots = !!ms->ram_slots,
|
|
|
|
.slots = ms->ram_slots,
|
|
|
|
};
|
|
|
|
MemorySizeConfiguration *p_mem = &mem;
|
|
|
|
|
|
|
|
visit_type_MemorySizeConfiguration(v, name, &p_mem, &error_abort);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_mem(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
|
|
|
{
|
2022-11-21 09:50:47 +01:00
|
|
|
ERRP_GUARD();
|
2022-04-14 18:52:58 +02:00
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
MachineClass *mc = MACHINE_GET_CLASS(obj);
|
|
|
|
MemorySizeConfiguration *mem;
|
|
|
|
|
|
|
|
if (!visit_type_MemorySizeConfiguration(v, name, &mem, errp)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mem->has_size) {
|
|
|
|
mem->has_size = true;
|
|
|
|
mem->size = mc->default_ram_size;
|
|
|
|
}
|
|
|
|
mem->size = QEMU_ALIGN_UP(mem->size, 8192);
|
|
|
|
if (mc->fixup_ram_size) {
|
|
|
|
mem->size = mc->fixup_ram_size(mem->size);
|
|
|
|
}
|
|
|
|
if ((ram_addr_t)mem->size != mem->size) {
|
|
|
|
error_setg(errp, "ram size too large");
|
|
|
|
goto out_free;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mem->has_max_size) {
|
|
|
|
if (mem->max_size < mem->size) {
|
|
|
|
error_setg(errp, "invalid value of maxmem: "
|
|
|
|
"maximum memory size (0x%" PRIx64 ") must be at least "
|
|
|
|
"the initial memory size (0x%" PRIx64 ")",
|
|
|
|
mem->max_size, mem->size);
|
|
|
|
goto out_free;
|
|
|
|
}
|
|
|
|
if (mem->has_slots && mem->slots && mem->max_size == mem->size) {
|
|
|
|
error_setg(errp, "invalid value of maxmem: "
|
|
|
|
"memory slots were specified but maximum memory size "
|
|
|
|
"(0x%" PRIx64 ") is equal to the initial memory size "
|
|
|
|
"(0x%" PRIx64 ")", mem->max_size, mem->size);
|
|
|
|
goto out_free;
|
|
|
|
}
|
|
|
|
ms->maxram_size = mem->max_size;
|
|
|
|
} else {
|
|
|
|
if (mem->has_slots) {
|
|
|
|
error_setg(errp, "slots specified but no max-size");
|
|
|
|
goto out_free;
|
|
|
|
}
|
|
|
|
ms->maxram_size = mem->size;
|
|
|
|
}
|
|
|
|
ms->ram_size = mem->size;
|
|
|
|
ms->ram_slots = mem->has_slots ? mem->slots : 0;
|
|
|
|
out_free:
|
|
|
|
qapi_free_MemorySizeConfiguration(mem);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2021-03-25 16:33:08 +01:00
|
|
|
bool device_is_dynamic_sysbus(MachineClass *mc, DeviceState *dev)
|
2014-07-01 16:14:41 +02:00
|
|
|
{
|
2021-03-25 16:33:08 +01:00
|
|
|
Object *obj = OBJECT(dev);
|
|
|
|
|
|
|
|
if (!object_dynamic_cast(obj, TYPE_SYS_BUS_DEVICE)) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-07-01 16:14:41 +02:00
|
|
|
|
2021-10-29 16:22:56 +02:00
|
|
|
return device_type_is_dynamic_sysbus(mc, object_get_typename(obj));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool device_type_is_dynamic_sysbus(MachineClass *mc, const char *type)
|
|
|
|
{
|
|
|
|
bool allowed = false;
|
|
|
|
strList *wl;
|
|
|
|
ObjectClass *klass = object_class_by_name(type);
|
|
|
|
|
2017-11-25 16:16:05 +01:00
|
|
|
for (wl = mc->allowed_dynamic_sysbus_devices;
|
|
|
|
!allowed && wl;
|
|
|
|
wl = wl->next) {
|
2021-10-29 16:22:56 +02:00
|
|
|
allowed |= !!object_class_dynamic_cast(klass, wl->value);
|
2017-11-25 16:16:05 +01:00
|
|
|
}
|
|
|
|
|
2021-03-25 16:33:08 +01:00
|
|
|
return allowed;
|
|
|
|
}
|
|
|
|
|
2022-04-25 10:21:50 +02:00
|
|
|
static char *machine_get_audiodev(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
return g_strdup(ms->audiodev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_audiodev(Object *obj, const char *value,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
|
|
|
if (!audio_state_by_name(value, errp)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(ms->audiodev);
|
|
|
|
ms->audiodev = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
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->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;
|
|
|
|
}
|
|
|
|
|
2022-05-03 16:02:59 +02:00
|
|
|
if (props->has_cluster_id && !slot->props.has_cluster_id) {
|
|
|
|
error_setg(errp, "cluster-id is not supported");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-10 13:29:50 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-05-03 16:02:59 +02:00
|
|
|
if (props->has_cluster_id &&
|
|
|
|
props->cluster_id != slot->props.cluster_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
|
2021-07-07 15:40:29 +02:00
|
|
|
" should be itself (got %" PRIu16 ")",
|
|
|
|
props->node_id, numa_info[props->node_id].initiator);
|
2019-12-13 02:19:22 +01:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-13 15:03:48 +02:00
|
|
|
static void machine_get_smp(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
SMPConfiguration *config = &(SMPConfiguration){
|
2021-09-29 04:58:11 +02:00
|
|
|
.has_cpus = true, .cpus = ms->smp.cpus,
|
2021-05-13 15:03:48 +02:00
|
|
|
.has_sockets = true, .sockets = ms->smp.sockets,
|
|
|
|
.has_dies = true, .dies = ms->smp.dies,
|
hw/core/machine: Introduce CPU cluster topology support
The new Cluster-Aware Scheduling support has landed in Linux 5.16,
which has been proved to benefit the scheduling performance (e.g.
load balance and wake_affine strategy) on both x86_64 and AArch64.
So now in Linux 5.16 we have four-level arch-neutral CPU topology
definition like below and a new scheduler level for clusters.
struct cpu_topology {
int thread_id;
int core_id;
int cluster_id;
int package_id;
int llc_id;
cpumask_t thread_sibling;
cpumask_t core_sibling;
cpumask_t cluster_sibling;
cpumask_t llc_sibling;
}
A cluster generally means a group of CPU cores which share L2 cache
or other mid-level resources, and it is the shared resources that
is used to improve scheduler's behavior. From the point of view of
the size range, it's between CPU die and CPU core. For example, on
some ARM64 Kunpeng servers, we have 6 clusters in each NUMA node,
and 4 CPU cores in each cluster. The 4 CPU cores share a separate
L2 cache and a L3 cache tag, which brings cache affinity advantage.
In virtualization, on the Hosts which have pClusters (physical
clusters), if we can design a vCPU topology with cluster level for
guest kernel and have a dedicated vCPU pinning. A Cluster-Aware
Guest kernel can also make use of the cache affinity of CPU clusters
to gain similar scheduling performance.
This patch adds infrastructure for CPU cluster level topology
configuration and parsing, so that the user can specify cluster
parameter if their machines support it.
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Message-Id: <20211228092221.21068-3-wangyanan55@huawei.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
[PMD: Added '(since 7.0)' to @clusters in qapi/machine.json]
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2021-12-28 10:22:09 +01:00
|
|
|
.has_clusters = true, .clusters = ms->smp.clusters,
|
2021-09-29 04:58:11 +02:00
|
|
|
.has_cores = true, .cores = ms->smp.cores,
|
2021-05-13 15:03:48 +02:00
|
|
|
.has_threads = true, .threads = ms->smp.threads,
|
|
|
|
.has_maxcpus = true, .maxcpus = ms->smp.max_cpus,
|
|
|
|
};
|
hw/core/machine: Introduce CPU cluster topology support
The new Cluster-Aware Scheduling support has landed in Linux 5.16,
which has been proved to benefit the scheduling performance (e.g.
load balance and wake_affine strategy) on both x86_64 and AArch64.
So now in Linux 5.16 we have four-level arch-neutral CPU topology
definition like below and a new scheduler level for clusters.
struct cpu_topology {
int thread_id;
int core_id;
int cluster_id;
int package_id;
int llc_id;
cpumask_t thread_sibling;
cpumask_t core_sibling;
cpumask_t cluster_sibling;
cpumask_t llc_sibling;
}
A cluster generally means a group of CPU cores which share L2 cache
or other mid-level resources, and it is the shared resources that
is used to improve scheduler's behavior. From the point of view of
the size range, it's between CPU die and CPU core. For example, on
some ARM64 Kunpeng servers, we have 6 clusters in each NUMA node,
and 4 CPU cores in each cluster. The 4 CPU cores share a separate
L2 cache and a L3 cache tag, which brings cache affinity advantage.
In virtualization, on the Hosts which have pClusters (physical
clusters), if we can design a vCPU topology with cluster level for
guest kernel and have a dedicated vCPU pinning. A Cluster-Aware
Guest kernel can also make use of the cache affinity of CPU clusters
to gain similar scheduling performance.
This patch adds infrastructure for CPU cluster level topology
configuration and parsing, so that the user can specify cluster
parameter if their machines support it.
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Message-Id: <20211228092221.21068-3-wangyanan55@huawei.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
[PMD: Added '(since 7.0)' to @clusters in qapi/machine.json]
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2021-12-28 10:22:09 +01:00
|
|
|
|
2021-05-13 15:03:48 +02:00
|
|
|
if (!visit_type_SMPConfiguration(v, name, &config, &error_abort)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_smp(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
2021-10-01 19:04:03 +02:00
|
|
|
g_autoptr(SMPConfiguration) config = NULL;
|
2021-05-13 15:03:48 +02:00
|
|
|
|
|
|
|
if (!visit_type_SMPConfiguration(v, name, &config, errp)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-11 10:21:23 +01:00
|
|
|
machine_parse_smp_config(ms, config, errp);
|
2021-05-13 15:03:48 +02:00
|
|
|
}
|
|
|
|
|
2022-04-14 18:52:57 +02:00
|
|
|
static void machine_get_boot(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
BootConfiguration *config = &ms->boot_config;
|
|
|
|
visit_type_BootConfiguration(v, name, &config, &error_abort);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_free_boot_config(MachineState *ms)
|
|
|
|
{
|
|
|
|
g_free(ms->boot_config.order);
|
|
|
|
g_free(ms->boot_config.once);
|
|
|
|
g_free(ms->boot_config.splash);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_copy_boot_config(MachineState *ms, BootConfiguration *config)
|
2022-04-14 18:52:56 +02:00
|
|
|
{
|
|
|
|
MachineClass *machine_class = MACHINE_GET_CLASS(ms);
|
2022-04-14 18:52:57 +02:00
|
|
|
|
|
|
|
machine_free_boot_config(ms);
|
|
|
|
ms->boot_config = *config;
|
2022-11-04 17:06:57 +01:00
|
|
|
if (!config->order) {
|
2022-04-14 18:52:57 +02:00
|
|
|
ms->boot_config.order = g_strdup(machine_class->default_boot_order);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_boot(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
|
|
|
{
|
2022-04-14 18:52:56 +02:00
|
|
|
ERRP_GUARD();
|
2022-04-14 18:52:57 +02:00
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
BootConfiguration *config = NULL;
|
2022-04-14 18:52:56 +02:00
|
|
|
|
2022-04-14 18:52:57 +02:00
|
|
|
if (!visit_type_BootConfiguration(v, name, &config, errp)) {
|
2022-04-14 18:52:56 +02:00
|
|
|
return;
|
|
|
|
}
|
2022-11-04 17:06:57 +01:00
|
|
|
if (config->order) {
|
2022-04-14 18:52:57 +02:00
|
|
|
validate_bootdevices(config->order, errp);
|
2022-04-14 18:52:56 +02:00
|
|
|
if (*errp) {
|
2022-04-14 18:52:57 +02:00
|
|
|
goto out_free;
|
2022-04-14 18:52:56 +02:00
|
|
|
}
|
|
|
|
}
|
2022-11-04 17:06:57 +01:00
|
|
|
if (config->once) {
|
2022-04-14 18:52:57 +02:00
|
|
|
validate_bootdevices(config->once, errp);
|
2022-04-14 18:52:56 +02:00
|
|
|
if (*errp) {
|
2022-04-14 18:52:57 +02:00
|
|
|
goto out_free;
|
2022-04-14 18:52:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-14 18:52:57 +02:00
|
|
|
machine_copy_boot_config(ms, config);
|
|
|
|
/* Strings live in ms->boot_config. */
|
|
|
|
free(config);
|
|
|
|
return;
|
2022-04-14 18:52:56 +02:00
|
|
|
|
2022-04-14 18:52:57 +02:00
|
|
|
out_free:
|
|
|
|
qapi_free_BootConfiguration(config);
|
2022-04-14 18:52:56 +02:00
|
|
|
}
|
|
|
|
|
2022-04-25 10:21:50 +02:00
|
|
|
void machine_add_audiodev_property(MachineClass *mc)
|
|
|
|
{
|
|
|
|
ObjectClass *oc = OBJECT_CLASS(mc);
|
|
|
|
|
|
|
|
object_class_property_add_str(oc, "audiodev",
|
|
|
|
machine_get_audiodev,
|
|
|
|
machine_set_audiodev);
|
|
|
|
object_class_property_set_description(oc, "audiodev",
|
|
|
|
"Audiodev to use for default machine devices");
|
|
|
|
}
|
|
|
|
|
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;
|
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
|
|
|
|
2022-04-14 18:52:57 +02:00
|
|
|
object_class_property_add(oc, "boot", "BootConfiguration",
|
|
|
|
machine_get_boot, machine_set_boot,
|
|
|
|
NULL, NULL);
|
|
|
|
object_class_property_set_description(oc, "boot",
|
|
|
|
"Boot configuration");
|
|
|
|
|
2021-05-13 15:03:48 +02:00
|
|
|
object_class_property_add(oc, "smp", "SMPConfiguration",
|
|
|
|
machine_get_smp, machine_set_smp,
|
|
|
|
NULL, NULL);
|
|
|
|
object_class_property_set_description(oc, "smp",
|
|
|
|
"CPU topology");
|
|
|
|
|
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
|
|
|
|
2020-12-04 02:51:51 +01:00
|
|
|
object_class_property_add_link(oc, "confidential-guest-support",
|
|
|
|
TYPE_CONFIDENTIAL_GUEST_SUPPORT,
|
|
|
|
offsetof(MachineState, cgs),
|
|
|
|
machine_check_confidential_guest_support,
|
|
|
|
OBJ_PROP_LINK_STRONG);
|
|
|
|
object_class_property_set_description(oc, "confidential-guest-support",
|
|
|
|
"Set confidential guest scheme to support");
|
|
|
|
|
|
|
|
/* For compatibility */
|
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
|
|
|
|
2022-04-14 18:52:59 +02:00
|
|
|
object_class_property_add_link(oc, "memory-backend", TYPE_MEMORY_BACKEND,
|
|
|
|
offsetof(MachineState, memdev), object_property_allow_set_link,
|
|
|
|
OBJ_PROP_LINK_STRONG);
|
2020-09-22 00:10:41 +02:00
|
|
|
object_class_property_set_description(oc, "memory-backend",
|
|
|
|
"Set RAM backend"
|
|
|
|
"Valid value is ID of hostmem based backend");
|
2022-04-14 18:52:58 +02:00
|
|
|
|
|
|
|
object_class_property_add(oc, "memory", "MemorySizeConfiguration",
|
|
|
|
machine_get_mem, machine_set_mem,
|
|
|
|
NULL, NULL);
|
|
|
|
object_class_property_set_description(oc, "memory",
|
|
|
|
"Memory size configuration");
|
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("");
|
2022-04-14 18:52:58 +02:00
|
|
|
ms->ram_size = mc->default_ram_size;
|
|
|
|
ms->maxram_size = mc->default_ram_size;
|
2015-02-04 16:43:49 +01:00
|
|
|
|
2019-03-08 19:20:53 +01:00
|
|
|
if (mc->nvdimm_supported) {
|
|
|
|
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
|
|
|
|
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;
|
2021-09-29 04:58:11 +02:00
|
|
|
ms->smp.sockets = 1;
|
2021-06-17 17:53:03 +02:00
|
|
|
ms->smp.dies = 1;
|
hw/core/machine: Introduce CPU cluster topology support
The new Cluster-Aware Scheduling support has landed in Linux 5.16,
which has been proved to benefit the scheduling performance (e.g.
load balance and wake_affine strategy) on both x86_64 and AArch64.
So now in Linux 5.16 we have four-level arch-neutral CPU topology
definition like below and a new scheduler level for clusters.
struct cpu_topology {
int thread_id;
int core_id;
int cluster_id;
int package_id;
int llc_id;
cpumask_t thread_sibling;
cpumask_t core_sibling;
cpumask_t cluster_sibling;
cpumask_t llc_sibling;
}
A cluster generally means a group of CPU cores which share L2 cache
or other mid-level resources, and it is the shared resources that
is used to improve scheduler's behavior. From the point of view of
the size range, it's between CPU die and CPU core. For example, on
some ARM64 Kunpeng servers, we have 6 clusters in each NUMA node,
and 4 CPU cores in each cluster. The 4 CPU cores share a separate
L2 cache and a L3 cache tag, which brings cache affinity advantage.
In virtualization, on the Hosts which have pClusters (physical
clusters), if we can design a vCPU topology with cluster level for
guest kernel and have a dedicated vCPU pinning. A Cluster-Aware
Guest kernel can also make use of the cache affinity of CPU clusters
to gain similar scheduling performance.
This patch adds infrastructure for CPU cluster level topology
configuration and parsing, so that the user can specify cluster
parameter if their machines support it.
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Message-Id: <20211228092221.21068-3-wangyanan55@huawei.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
[PMD: Added '(since 7.0)' to @clusters in qapi/machine.json]
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2021-12-28 10:22:09 +01:00
|
|
|
ms->smp.clusters = 1;
|
2021-09-29 04:58:11 +02:00
|
|
|
ms->smp.cores = 1;
|
2020-10-21 12:45:14 +02:00
|
|
|
ms->smp.threads = 1;
|
2022-04-14 18:52:57 +02:00
|
|
|
|
|
|
|
machine_copy_boot_config(ms, &(BootConfiguration){ 0 });
|
2014-05-26 14:40:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_finalize(Object *obj)
|
|
|
|
{
|
|
|
|
MachineState *ms = MACHINE(obj);
|
|
|
|
|
2022-04-14 18:52:57 +02:00
|
|
|
machine_free_boot_config(ms);
|
2014-05-26 14:40:58 +02:00
|
|
|
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);
|
2022-04-25 10:21:50 +02:00
|
|
|
g_free(ms->audiodev);
|
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) {
|
2021-10-08 09:50:40 +02:00
|
|
|
if (s->len) {
|
|
|
|
g_string_append_printf(s, ", ");
|
|
|
|
}
|
2019-06-12 10:40:58 +02:00
|
|
|
g_string_append_printf(s, "die-id: %"PRId64, cpu->props.die_id);
|
|
|
|
}
|
2022-05-03 16:02:59 +02:00
|
|
|
if (cpu->props.has_cluster_id) {
|
|
|
|
if (s->len) {
|
|
|
|
g_string_append_printf(s, ", ");
|
|
|
|
}
|
|
|
|
g_string_append_printf(s, "cluster-id: %"PRId64, cpu->props.cluster_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) {
|
hmat acpi: Don't require initiator value in -numa
The "Memory Proximity Domain Attributes" structure of the ACPI HMAT
has a "Processor Proximity Domain Valid" flag that is currently
always set because Qemu -numa requires an initiator=X value
when hmat=on. Unsetting this flag allows to create more complex
memory topologies by having multiple best initiators for a single
memory target.
This patch allows -numa without initiator=X when hmat=on by keeping
the default value MAX_NODES in numa_state->nodes[i].initiator.
All places reading numa_state->nodes[i].initiator already check
whether it's different from MAX_NODES before using it.
Tested with
qemu-system-x86_64 -accel kvm \
-machine pc,hmat=on \
-drive if=pflash,format=raw,file=./OVMF.fd \
-drive media=disk,format=qcow2,file=efi.qcow2 \
-smp 4 \
-m 3G \
-object memory-backend-ram,size=1G,id=ram0 \
-object memory-backend-ram,size=1G,id=ram1 \
-object memory-backend-ram,size=1G,id=ram2 \
-numa node,nodeid=0,memdev=ram0,cpus=0-1 \
-numa node,nodeid=1,memdev=ram1,cpus=2-3 \
-numa node,nodeid=2,memdev=ram2 \
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,latency=10 \
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,bandwidth=10485760 \
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,latency=20 \
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,bandwidth=5242880 \
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,latency=30 \
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,bandwidth=1048576 \
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,latency=20 \
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,bandwidth=5242880 \
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,latency=10 \
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,bandwidth=10485760 \
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,latency=30 \
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,bandwidth=1048576
which reports NUMA node2 at same distance from both node0 and node1 as seen in lstopo:
Machine (2966MB total) + Package P#0
NUMANode P#2 (979MB)
Group0
NUMANode P#0 (980MB)
Core P#0 + PU P#0
Core P#1 + PU P#1
Group0
NUMANode P#1 (1007MB)
Core P#2 + PU P#2
Core P#3 + PU P#3
Before this patch, we had to add ",initiator=X" to "-numa node,nodeid=2,memdev=ram2".
The lstopo output difference between initiator=1 and no initiator is:
@@ -1,10 +1,10 @@
Machine (2966MB total) + Package P#0
+ NUMANode P#2 (979MB)
Group0
NUMANode P#0 (980MB)
Core P#0 + PU P#0
Core P#1 + PU P#1
Group0
NUMANode P#1 (1007MB)
- NUMANode P#2 (979MB)
Core P#2 + PU P#2
Core P#3 + PU P#3
Corresponding changes in the HMAT MPDA structure:
@@ -49,10 +49,10 @@
[078h 0120 2] Structure Type : 0000 [Memory Proximity Domain Attributes]
[07Ah 0122 2] Reserved : 0000
[07Ch 0124 4] Length : 00000028
-[080h 0128 2] Flags (decoded below) : 0001
- Processor Proximity Domain Valid : 1
+[080h 0128 2] Flags (decoded below) : 0000
+ Processor Proximity Domain Valid : 0
[082h 0130 2] Reserved1 : 0000
-[084h 0132 4] Attached Initiator Proximity Domain : 00000001
+[084h 0132 4] Attached Initiator Proximity Domain : 00000080
[088h 0136 4] Memory Proximity Domain : 00000002
[08Ch 0140 4] Reserved2 : 00000000
[090h 0144 8] Reserved3 : 0000000000000000
Final HMAT SLLB structures:
[0A0h 0160 2] Structure Type : 0001 [System Locality Latency and Bandwidth Information]
[0A2h 0162 2] Reserved : 0000
[0A4h 0164 4] Length : 00000040
[0A8h 0168 1] Flags (decoded below) : 00
Memory Hierarchy : 0
[0A9h 0169 1] Data Type : 00
[0AAh 0170 2] Reserved1 : 0000
[0ACh 0172 4] Initiator Proximity Domains # : 00000002
[0B0h 0176 4] Target Proximity Domains # : 00000003
[0B4h 0180 4] Reserved2 : 00000000
[0B8h 0184 8] Entry Base Unit : 0000000000002710
[0C0h 0192 4] Initiator Proximity Domain List : 00000000
[0C4h 0196 4] Initiator Proximity Domain List : 00000001
[0C8h 0200 4] Target Proximity Domain List : 00000000
[0CCh 0204 4] Target Proximity Domain List : 00000001
[0D0h 0208 4] Target Proximity Domain List : 00000002
[0D4h 0212 2] Entry : 0001
[0D6h 0214 2] Entry : 0002
[0D8h 0216 2] Entry : 0003
[0DAh 0218 2] Entry : 0002
[0DCh 0220 2] Entry : 0001
[0DEh 0222 2] Entry : 0003
[0E0h 0224 2] Structure Type : 0001 [System Locality Latency and Bandwidth Information]
[0E2h 0226 2] Reserved : 0000
[0E4h 0228 4] Length : 00000040
[0E8h 0232 1] Flags (decoded below) : 00
Memory Hierarchy : 0
[0E9h 0233 1] Data Type : 03
[0EAh 0234 2] Reserved1 : 0000
[0ECh 0236 4] Initiator Proximity Domains # : 00000002
[0F0h 0240 4] Target Proximity Domains # : 00000003
[0F4h 0244 4] Reserved2 : 00000000
[0F8h 0248 8] Entry Base Unit : 0000000000000001
[100h 0256 4] Initiator Proximity Domain List : 00000000
[104h 0260 4] Initiator Proximity Domain List : 00000001
[108h 0264 4] Target Proximity Domain List : 00000000
[10Ch 0268 4] Target Proximity Domain List : 00000001
[110h 0272 4] Target Proximity Domain List : 00000002
[114h 0276 2] Entry : 000A
[116h 0278 2] Entry : 0005
[118h 0280 2] Entry : 0001
[11Ah 0282 2] Entry : 0005
[11Ch 0284 2] Entry : 000A
[11Eh 0286 2] Entry : 0001
Signed-off-by: Brice Goglin <Brice.Goglin@inria.fr>
Signed-off-by: Hesham Almatary <hesham.almatary@huawei.com>
Reviewed-by: Jingqi Liu <jingqi.liu@intel.com>
Message-Id: <20221027100037.251-2-hesham.almatary@huawei.com>
Tested-by: Yicong Yang <yangyicong@hisilicon.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-10-27 12:00:30 +02:00
|
|
|
continue;
|
2019-12-13 02:19:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
numa: Validate cluster and NUMA node boundary if required
For some architectures like ARM64, multiple CPUs in one cluster can be
associated with different NUMA nodes, which is irregular configuration
because we shouldn't have this in baremetal environment. The irregular
configuration causes Linux guest to misbehave, as the following warning
messages indicate.
-smp 6,maxcpus=6,sockets=2,clusters=1,cores=3,threads=1 \
-numa node,nodeid=0,cpus=0-1,memdev=ram0 \
-numa node,nodeid=1,cpus=2-3,memdev=ram1 \
-numa node,nodeid=2,cpus=4-5,memdev=ram2 \
------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at kernel/sched/topology.c:2271 build_sched_domains+0x284/0x910
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.14.0-268.el9.aarch64 #1
pstate: 00400005 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : build_sched_domains+0x284/0x910
lr : build_sched_domains+0x184/0x910
sp : ffff80000804bd50
x29: ffff80000804bd50 x28: 0000000000000002 x27: 0000000000000000
x26: ffff800009cf9a80 x25: 0000000000000000 x24: ffff800009cbf840
x23: ffff000080325000 x22: ffff0000005df800 x21: ffff80000a4ce508
x20: 0000000000000000 x19: ffff000080324440 x18: 0000000000000014
x17: 00000000388925c0 x16: 000000005386a066 x15: 000000009c10cc2e
x14: 00000000000001c0 x13: 0000000000000001 x12: ffff00007fffb1a0
x11: ffff00007fffb180 x10: ffff80000a4ce508 x9 : 0000000000000041
x8 : ffff80000a4ce500 x7 : ffff80000a4cf920 x6 : 0000000000000001
x5 : 0000000000000001 x4 : 0000000000000007 x3 : 0000000000000002
x2 : 0000000000001000 x1 : ffff80000a4cf928 x0 : 0000000000000001
Call trace:
build_sched_domains+0x284/0x910
sched_init_domains+0xac/0xe0
sched_init_smp+0x48/0xc8
kernel_init_freeable+0x140/0x1ac
kernel_init+0x28/0x140
ret_from_fork+0x10/0x20
Improve the situation to warn when multiple CPUs in one cluster have
been associated with different NUMA nodes. However, one NUMA node is
allowed to be associated with different clusters.
Signed-off-by: Gavin Shan <gshan@redhat.com>
Acked-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Acked-by: Igor Mammedov <imammedo@redhat.com>
Message-Id: <20230509002739.18388-2-gshan@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2023-05-09 02:27:37 +02:00
|
|
|
static void validate_cpu_cluster_to_numa_boundary(MachineState *ms)
|
|
|
|
{
|
|
|
|
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
|
|
|
NumaState *state = ms->numa_state;
|
|
|
|
const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
|
|
|
|
const CPUArchId *cpus = possible_cpus->cpus;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
if (state->num_nodes <= 1 || possible_cpus->len <= 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The Linux scheduling domain can't be parsed when the multiple CPUs
|
|
|
|
* in one cluster have been associated with different NUMA nodes. However,
|
|
|
|
* it's fine to associate one NUMA node with CPUs in different clusters.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < possible_cpus->len; i++) {
|
|
|
|
for (j = i + 1; j < possible_cpus->len; j++) {
|
|
|
|
if (cpus[i].props.has_socket_id &&
|
|
|
|
cpus[i].props.has_cluster_id &&
|
|
|
|
cpus[i].props.has_node_id &&
|
|
|
|
cpus[j].props.has_socket_id &&
|
|
|
|
cpus[j].props.has_cluster_id &&
|
|
|
|
cpus[j].props.has_node_id &&
|
|
|
|
cpus[i].props.socket_id == cpus[j].props.socket_id &&
|
|
|
|
cpus[i].props.cluster_id == cpus[j].props.cluster_id &&
|
|
|
|
cpus[i].props.node_id != cpus[j].props.node_id) {
|
|
|
|
warn_report("CPU-%d and CPU-%d in socket-%" PRId64 "-cluster-%" PRId64
|
|
|
|
" have been associated with node-%" PRId64 " and node-%" PRId64
|
|
|
|
" respectively. It can cause OSes like Linux to"
|
|
|
|
" misbehave", i, j, cpus[i].props.socket_id,
|
|
|
|
cpus[i].props.cluster_id, cpus[i].props.node_id,
|
|
|
|
cpus[j].props.node_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-19 17:08:38 +01:00
|
|
|
MemoryRegion *machine_consume_memdev(MachineState *machine,
|
|
|
|
HostMemoryBackend *backend)
|
|
|
|
{
|
|
|
|
MemoryRegion *ret = host_memory_backend_get_memory(backend);
|
|
|
|
|
2021-11-02 17:43:15 +01:00
|
|
|
if (host_memory_backend_is_mapped(backend)) {
|
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;
|
|
|
|
}
|
|
|
|
|
2022-04-14 18:52:59 +02:00
|
|
|
static bool create_default_memdev(MachineState *ms, const char *path, Error **errp)
|
|
|
|
{
|
|
|
|
Object *obj;
|
|
|
|
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
|
|
|
bool r = false;
|
|
|
|
|
|
|
|
obj = object_new(path ? TYPE_MEMORY_BACKEND_FILE : TYPE_MEMORY_BACKEND_RAM);
|
|
|
|
if (path) {
|
|
|
|
if (!object_property_set_str(obj, "mem-path", path, errp)) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!object_property_set_int(obj, "size", ms->ram_size, errp)) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
object_property_add_child(object_get_objects_root(), mc->default_ram_id,
|
|
|
|
obj);
|
|
|
|
/* Ensure backend's memory region name is equal to mc->default_ram_id */
|
|
|
|
if (!object_property_set_bool(obj, "x-use-canonical-path-for-ramblock-id",
|
|
|
|
false, errp)) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (!user_creatable_complete(USER_CREATABLE(obj), errp)) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
r = object_property_set_link(OBJECT(ms), "memory-backend", obj, errp);
|
|
|
|
|
|
|
|
out:
|
|
|
|
object_unref(obj);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void machine_run_board_init(MachineState *machine, const char *mem_path, Error **errp)
|
2017-05-10 13:29:58 +02:00
|
|
|
{
|
2023-09-06 14:05:03 +02:00
|
|
|
ERRP_GUARD();
|
2017-05-10 13:29:58 +02:00
|
|
|
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);
|
|
|
|
|
2022-04-14 18:53:00 +02:00
|
|
|
if (!xen_enabled()) {
|
|
|
|
/* On 32-bit hosts, QEMU is limited by virtual address space */
|
|
|
|
if (machine->ram_size > (2047 << 20) && HOST_LONG_BITS == 32) {
|
|
|
|
error_setg(errp, "at most 2047 MB RAM can be simulated");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (machine->memdev) {
|
|
|
|
ram_addr_t backend_size = object_property_get_uint(OBJECT(machine->memdev),
|
|
|
|
"size", &error_abort);
|
|
|
|
if (backend_size != machine->ram_size) {
|
|
|
|
error_setg(errp, "Machine memory size does not match the size of the memory backend");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (machine_class->default_ram_id && machine->ram_size &&
|
|
|
|
numa_uses_legacy_mem()) {
|
2023-05-22 15:17:17 +02:00
|
|
|
if (object_property_find(object_get_objects_root(),
|
|
|
|
machine_class->default_ram_id)) {
|
2023-09-06 14:05:03 +02:00
|
|
|
error_setg(errp, "object's id '%s' is reserved for the default"
|
|
|
|
" RAM backend, it can't be used for any other purposes",
|
|
|
|
machine_class->default_ram_id);
|
|
|
|
error_append_hint(errp,
|
|
|
|
"Change the object's 'id' to something else or disable"
|
|
|
|
" automatic creation of the default RAM backend by setting"
|
|
|
|
" 'memory-backend=%s' with '-machine'.\n",
|
2023-05-22 15:17:17 +02:00
|
|
|
machine_class->default_ram_id);
|
|
|
|
return;
|
|
|
|
}
|
2022-04-14 18:52:59 +02:00
|
|
|
if (!create_default_memdev(current_machine, mem_path, errp)) {
|
|
|
|
return;
|
|
|
|
}
|
2020-02-19 17:08:38 +01:00
|
|
|
}
|
|
|
|
|
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);
|
numa: Validate cluster and NUMA node boundary if required
For some architectures like ARM64, multiple CPUs in one cluster can be
associated with different NUMA nodes, which is irregular configuration
because we shouldn't have this in baremetal environment. The irregular
configuration causes Linux guest to misbehave, as the following warning
messages indicate.
-smp 6,maxcpus=6,sockets=2,clusters=1,cores=3,threads=1 \
-numa node,nodeid=0,cpus=0-1,memdev=ram0 \
-numa node,nodeid=1,cpus=2-3,memdev=ram1 \
-numa node,nodeid=2,cpus=4-5,memdev=ram2 \
------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at kernel/sched/topology.c:2271 build_sched_domains+0x284/0x910
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.14.0-268.el9.aarch64 #1
pstate: 00400005 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : build_sched_domains+0x284/0x910
lr : build_sched_domains+0x184/0x910
sp : ffff80000804bd50
x29: ffff80000804bd50 x28: 0000000000000002 x27: 0000000000000000
x26: ffff800009cf9a80 x25: 0000000000000000 x24: ffff800009cbf840
x23: ffff000080325000 x22: ffff0000005df800 x21: ffff80000a4ce508
x20: 0000000000000000 x19: ffff000080324440 x18: 0000000000000014
x17: 00000000388925c0 x16: 000000005386a066 x15: 000000009c10cc2e
x14: 00000000000001c0 x13: 0000000000000001 x12: ffff00007fffb1a0
x11: ffff00007fffb180 x10: ffff80000a4ce508 x9 : 0000000000000041
x8 : ffff80000a4ce500 x7 : ffff80000a4cf920 x6 : 0000000000000001
x5 : 0000000000000001 x4 : 0000000000000007 x3 : 0000000000000002
x2 : 0000000000001000 x1 : ffff80000a4cf928 x0 : 0000000000000001
Call trace:
build_sched_domains+0x284/0x910
sched_init_domains+0xac/0xe0
sched_init_smp+0x48/0xc8
kernel_init_freeable+0x140/0x1ac
kernel_init+0x28/0x140
ret_from_fork+0x10/0x20
Improve the situation to warn when multiple CPUs in one cluster have
been associated with different NUMA nodes. However, one NUMA node is
allowed to be associated with different clusters.
Signed-off-by: Gavin Shan <gshan@redhat.com>
Acked-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Acked-by: Igor Mammedov <imammedo@redhat.com>
Message-Id: <20230509002739.18388-2-gshan@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2023-05-09 02:27:37 +02:00
|
|
|
if (machine_class->cpu_cluster_has_numa_boundary) {
|
|
|
|
validate_cpu_cluster_to_numa_boundary(machine);
|
|
|
|
}
|
2019-08-09 08:57:22 +02:00
|
|
|
}
|
2018-07-10 12:51:29 +02:00
|
|
|
}
|
2017-10-03 22:05:09 +02:00
|
|
|
|
2022-04-14 18:52:59 +02:00
|
|
|
if (!machine->ram && machine->memdev) {
|
|
|
|
machine->ram = machine_consume_memdev(machine, machine->memdev);
|
|
|
|
}
|
|
|
|
|
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])) {
|
2023-07-14 13:32:24 +02:00
|
|
|
/* The user specified CPU is in the valid field, we are
|
2017-10-03 22:05:09 +02:00
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2020-12-04 02:51:51 +01:00
|
|
|
if (machine->cgs) {
|
2020-07-24 04:57:37 +02:00
|
|
|
/*
|
2020-12-04 02:51:51 +01:00
|
|
|
* With confidential guests, the host can't see the real
|
2020-07-24 04:57:37 +02:00
|
|
|
* contents of RAM, so there's no point in it trying to merge
|
|
|
|
* areas.
|
|
|
|
*/
|
|
|
|
machine_set_mem_merge(OBJECT(machine), false, &error_abort);
|
2020-06-04 06:20:24 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Virtio devices can't count on directly accessing guest
|
|
|
|
* memory, so they need iommu_platform=on to use normal DMA
|
|
|
|
* mechanisms. That requires also disabling legacy virtio
|
|
|
|
* support for those virtio pci devices which allow it.
|
|
|
|
*/
|
|
|
|
object_register_sugar_prop(TYPE_VIRTIO_PCI, "disable-legacy",
|
|
|
|
"on", true);
|
|
|
|
object_register_sugar_prop(TYPE_VIRTIO_DEVICE, "iommu_platform",
|
|
|
|
"on", false);
|
2020-07-24 04:57:37 +02:00
|
|
|
}
|
|
|
|
|
2021-03-22 14:27:58 +01:00
|
|
|
accel_init_interfaces(ACCEL_GET_CLASS(machine->accelerator));
|
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();
|
|
|
|
|
2022-11-04 17:06:57 +01:00
|
|
|
if (current_machine->boot_config.once) {
|
2022-04-14 18:52:56 +02:00
|
|
|
qemu_boot_set(current_machine->boot_config.once, &error_fatal);
|
|
|
|
qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_config.order));
|
2020-11-13 08:43:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)
|