update live migration patches

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
master
Wolfgang Bumiller 2019-07-11 09:29:20 +02:00
parent 8b017a9a20
commit 99c47abaac
5 changed files with 134 additions and 162 deletions

View File

@ -32,3 +32,6 @@ index d6bb57d210..ee4b8b47e2 100644
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
--
2.20.1

View File

@ -28,3 +28,6 @@ index ee4b8b47e2..331a364a1b 100644
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
--
2.20.1

View File

@ -0,0 +1,127 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Wed, 10 Jul 2019 16:14:40 +0200
Subject: [PATCH] virtio-balloon: fix QEMU 4.0 config size migration
incompatibility
The virtio-balloon config size changed in QEMU 4.0 even for existing
machine types. Migration from QEMU 3.1 to 4.0 can fail in some
circumstances with the following error:
qemu-system-x86_64: get_pci_config_device: Bad config data: i=0x10 read: a1 device: 1 cmask: ff wmask: c0 w1cmask:0
This happens because the virtio-balloon config size affects the VIRTIO
Legacy I/O Memory PCI BAR size.
Introduce a qdev property called "qemu-4-0-config-size" and enable it
only for the QEMU 4.0 machine types. This way <4.0 machine types use
the old size, 4.0 uses the larger size, and >4.0 machine types use the
appropriate size depending on enabled virtio-balloon features.
Live migration to and from old QEMUs to QEMU 4.1 works again as long as
a versioned machine type is specified (do not use just "pc"!).
Originally-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
hw/core/machine.c | 1 +
hw/virtio/virtio-balloon.c | 28 +++++++++++++++++++++++++---
include/hw/virtio/virtio-balloon.h | 2 ++
3 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 743fef2898..f25c91875f 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -36,6 +36,7 @@ GlobalProperty hw_compat_3_1[] = {
{ "usb-kbd", "serial", "42" },
{ "virtio-blk-device", "discard", "false" },
{ "virtio-blk-device", "write-zeroes", "false" },
+ { "virtio-balloon-device", "qemu-4-0-config-size", "false" },
};
const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1);
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index d96e4aa96f..c8788ea18d 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -615,6 +615,22 @@ virtio_balloon_free_page_report_notify(NotifierWithReturn *n, void *data)
return 0;
}
+static size_t virtio_balloon_config_size(VirtIOBalloon *s)
+{
+ uint64_t features = s->host_features;
+
+ if (s->qemu_4_0_config_size) {
+ return sizeof(struct virtio_balloon_config);
+ }
+ if (virtio_has_feature(features, VIRTIO_BALLOON_F_PAGE_POISON)) {
+ return sizeof(struct virtio_balloon_config);
+ }
+ if (virtio_has_feature(features, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) {
+ return offsetof(struct virtio_balloon_config, poison_val);
+ }
+ return offsetof(struct virtio_balloon_config, free_page_report_cmd_id);
+}
+
static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
{
VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
@@ -635,7 +651,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
}
trace_virtio_balloon_get_config(config.num_pages, config.actual);
- memcpy(config_data, &config, sizeof(struct virtio_balloon_config));
+ memcpy(config_data, &config, virtio_balloon_config_size(dev));
}
static int build_dimm_list(Object *obj, void *opaque)
@@ -679,7 +695,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
uint32_t oldactual = dev->actual;
ram_addr_t vm_ram_size = get_current_ram_size();
- memcpy(&config, config_data, sizeof(struct virtio_balloon_config));
+ memcpy(&config, config_data, virtio_balloon_config_size(dev));
dev->actual = le32_to_cpu(config.actual);
if (dev->actual != oldactual) {
qapi_event_send_balloon_change(vm_ram_size -
@@ -795,7 +811,7 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
int ret;
virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON,
- sizeof(struct virtio_balloon_config));
+ virtio_balloon_config_size(s));
ret = qemu_add_balloon_handler(virtio_balloon_to_target,
virtio_balloon_stat, s);
@@ -926,6 +942,12 @@ static Property virtio_balloon_properties[] = {
VIRTIO_BALLOON_F_DEFLATE_ON_OOM, false),
DEFINE_PROP_BIT("free-page-hint", VirtIOBalloon, host_features,
VIRTIO_BALLOON_F_FREE_PAGE_HINT, false),
+ /* QEMU 4.0 accidentally changed the config size even when free-page-hint
+ * is disabled, resulting in QEMU 3.1 migration incompatibility. This
+ * property retains this quirk for QEMU 4.1 machine types.
+ */
+ DEFINE_PROP_BOOL("qemu-4-0-config-size", VirtIOBalloon,
+ qemu_4_0_config_size, false),
DEFINE_PROP_LINK("iothread", VirtIOBalloon, iothread, TYPE_IOTHREAD,
IOThread *),
DEFINE_PROP_END_OF_LIST(),
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
index 1afafb12f6..5a99293a45 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -71,6 +71,8 @@ typedef struct VirtIOBalloon {
int64_t stats_poll_interval;
uint32_t host_features;
PartiallyBalloonedPage *pbp;
+
+ bool qemu_4_0_config_size;
} VirtIOBalloon;
#endif
--
2.20.1

View File

@ -1,161 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Tue, 2 Jul 2019 09:23:43 +0200
Subject: [PATCH] virtio-balloon: use smaller config on older guests
The increased config size changes its alignment requirements
preventing guests from migrating from old qemu versions if
their balloon mapping isn't stricter aligned.
So base the default config size on the machine version.
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
hw/i386/pc.c | 2 ++
hw/virtio/virtio-balloon.c | 52 +++++++++++++++++++++++++++---
include/hw/virtio/virtio-balloon.h | 1 +
3 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index f2c15bf1f2..a6c01203f5 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -77,6 +77,7 @@
#include "hw/i386/intel_iommu.h"
#include "hw/net/ne2000-isa.h"
#include "standard-headers/asm-x86/bootparam.h"
+#include "hw/virtio/virtio-balloon.h"
/* debug PC/ISA interrupts */
//#define DEBUG_IRQ
@@ -137,6 +138,7 @@ GlobalProperty pc_compat_3_1[] = {
{ "Icelake-Server" "-" TYPE_X86_CPU, "mpx", "on" },
{ "Cascadelake-Server" "-" TYPE_X86_CPU, "stepping", "5" },
{ TYPE_X86_CPU, "x-intel-pt-auto-level", "off" },
+ { TYPE_VIRTIO_BALLOON, "x-use-large-balloon-config", "off" },
};
const size_t pc_compat_3_1_len = G_N_ELEMENTS(pc_compat_3_1);
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 2112874055..d10298786d 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -328,6 +328,28 @@ static void balloon_stats_set_poll_interval(Object *obj, Visitor *v,
balloon_stats_change_timer(s, 0);
}
+static void balloon_get_large_config(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ VirtIOBalloon *s = opaque;
+ visit_type_bool(v, name, &s->use_large_config, errp);
+}
+
+static void balloon_set_large_config(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ VirtIOBalloon *s = opaque;
+ DeviceState *dev = DEVICE(s);
+
+ if (dev->realized) {
+ error_setg(errp, "balloon config size cannot be changed at runtime");
+ } else {
+ visit_type_bool(v, name, &s->use_large_config, errp);
+ }
+}
+
static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
@@ -526,6 +548,17 @@ static bool virtio_balloon_free_page_support(void *opaque)
return virtio_vdev_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT);
}
+static size_t virtio_balloon_config_size(void *opaque)
+{
+ VirtIOBalloon *s = opaque;
+
+ if (s->use_large_config) {
+ return sizeof(struct virtio_balloon_config);
+ } else {
+ return offsetof(struct virtio_balloon_config, free_page_report_cmd_id);
+ }
+}
+
static void virtio_balloon_free_page_start(VirtIOBalloon *s)
{
VirtIODevice *vdev = VIRTIO_DEVICE(s);
@@ -635,7 +668,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
}
trace_virtio_balloon_get_config(config.num_pages, config.actual);
- memcpy(config_data, &config, sizeof(struct virtio_balloon_config));
+ memcpy(config_data, &config, virtio_balloon_config_size(dev));
}
static int build_dimm_list(Object *obj, void *opaque)
@@ -679,7 +712,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
uint32_t oldactual = dev->actual;
ram_addr_t vm_ram_size = get_current_ram_size();
- memcpy(&config, config_data, sizeof(struct virtio_balloon_config));
+ memcpy(&config, config_data, virtio_balloon_config_size(dev));
dev->actual = le32_to_cpu(config.actual);
if (dev->actual != oldactual) {
qapi_event_send_balloon_change(vm_ram_size -
@@ -766,7 +799,7 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
int ret;
virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON,
- sizeof(struct virtio_balloon_config));
+ virtio_balloon_config_size(s));
ret = qemu_add_balloon_handler(virtio_balloon_to_target,
virtio_balloon_stat, s);
@@ -791,7 +824,7 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
s->free_page_report_notify.notify =
virtio_balloon_free_page_report_notify;
precopy_add_notifier(&s->free_page_report_notify);
- if (s->iothread) {
+ if (s->iothread && s->use_large_config) {
object_ref(OBJECT(s->iothread));
s->free_page_bh = aio_bh_new(iothread_get_aio_context(s->iothread),
virtio_ballloon_get_free_page_hints, s);
@@ -804,6 +837,11 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
virtio_error(vdev, "iothread is missing");
}
}
+
+ if (!s->use_large_config) {
+ s->host_features &= ~(1 << VIRTIO_BALLOON_F_PAGE_POISON);
+ }
+
reset_stats(s);
}
@@ -880,6 +918,12 @@ static void virtio_balloon_instance_init(Object *obj)
balloon_stats_get_poll_interval,
balloon_stats_set_poll_interval,
NULL, s, NULL);
+
+ s->use_large_config = true;
+ object_property_add(obj, "x-use-large-balloon-config", "bool",
+ balloon_get_large_config,
+ balloon_set_large_config,
+ NULL, s, NULL);
}
static const VMStateDescription vmstate_virtio_balloon = {
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
index 1afafb12f6..f212c08bd7 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -45,6 +45,7 @@ enum virtio_balloon_free_page_report_status {
typedef struct VirtIOBalloon {
VirtIODevice parent_obj;
VirtQueue *ivq, *dvq, *svq, *free_page_vq;
+ bool use_large_config;
uint32_t free_page_report_status;
uint32_t num_pages;
uint32_t actual;

View File

@ -1,6 +1,6 @@
extra/0001-target-i386-add-MDS-NO-feature.patch
extra/0002-target-i386-define-md-clear-bit.patch
extra/0003-virtio-balloon-use-smaller-config-on-older-guests.patch
extra/0003-virtio-balloon-fix-QEMU-4.0-config-size-migration-in.patch
pve/0001-PVE-Config-block-file-change-locking-default-to-off.patch
pve/0002-PVE-Config-Adjust-network-script-path-to-etc-kvm.patch
pve/0003-PVE-Config-set-the-CPU-model-to-kvm64-32-instead-of-.patch