]>
Commit | Line | Data |
---|---|---|
d5699f03 TL |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Wolfgang Bumiller <w.bumiller@proxmox.com> | |
3 | Date: Tue, 2 Jul 2019 09:23:43 +0200 | |
4 | Subject: [PATCH] virtio-balloon: use smaller config on older guests | |
5 | ||
6 | The increased config size changes its alignment requirements | |
7 | preventing guests from migrating from old qemu versions if | |
8 | their balloon mapping isn't stricter aligned. | |
9 | So base the default config size on the machine version. | |
10 | ||
11 | Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> | |
12 | --- | |
13 | hw/i386/pc.c | 2 ++ | |
14 | hw/virtio/virtio-balloon.c | 52 +++++++++++++++++++++++++++--- | |
15 | include/hw/virtio/virtio-balloon.h | 1 + | |
16 | 3 files changed, 51 insertions(+), 4 deletions(-) | |
17 | ||
18 | diff --git a/hw/i386/pc.c b/hw/i386/pc.c | |
19 | index f2c15bf1f2..a6c01203f5 100644 | |
20 | --- a/hw/i386/pc.c | |
21 | +++ b/hw/i386/pc.c | |
22 | @@ -77,6 +77,7 @@ | |
23 | #include "hw/i386/intel_iommu.h" | |
24 | #include "hw/net/ne2000-isa.h" | |
25 | #include "standard-headers/asm-x86/bootparam.h" | |
26 | +#include "hw/virtio/virtio-balloon.h" | |
27 | ||
28 | /* debug PC/ISA interrupts */ | |
29 | //#define DEBUG_IRQ | |
30 | @@ -137,6 +138,7 @@ GlobalProperty pc_compat_3_1[] = { | |
31 | { "Icelake-Server" "-" TYPE_X86_CPU, "mpx", "on" }, | |
32 | { "Cascadelake-Server" "-" TYPE_X86_CPU, "stepping", "5" }, | |
33 | { TYPE_X86_CPU, "x-intel-pt-auto-level", "off" }, | |
34 | + { TYPE_VIRTIO_BALLOON, "x-use-large-balloon-config", "off" }, | |
35 | }; | |
36 | const size_t pc_compat_3_1_len = G_N_ELEMENTS(pc_compat_3_1); | |
37 | ||
38 | diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c | |
39 | index 2112874055..d10298786d 100644 | |
40 | --- a/hw/virtio/virtio-balloon.c | |
41 | +++ b/hw/virtio/virtio-balloon.c | |
42 | @@ -328,6 +328,28 @@ static void balloon_stats_set_poll_interval(Object *obj, Visitor *v, | |
43 | balloon_stats_change_timer(s, 0); | |
44 | } | |
45 | ||
46 | +static void balloon_get_large_config(Object *obj, Visitor *v, | |
47 | + const char *name, void *opaque, | |
48 | + Error **errp) | |
49 | +{ | |
50 | + VirtIOBalloon *s = opaque; | |
51 | + visit_type_bool(v, name, &s->use_large_config, errp); | |
52 | +} | |
53 | + | |
54 | +static void balloon_set_large_config(Object *obj, Visitor *v, | |
55 | + const char *name, void *opaque, | |
56 | + Error **errp) | |
57 | +{ | |
58 | + VirtIOBalloon *s = opaque; | |
59 | + DeviceState *dev = DEVICE(s); | |
60 | + | |
61 | + if (dev->realized) { | |
62 | + error_setg(errp, "balloon config size cannot be changed at runtime"); | |
63 | + } else { | |
64 | + visit_type_bool(v, name, &s->use_large_config, errp); | |
65 | + } | |
66 | +} | |
67 | + | |
68 | static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) | |
69 | { | |
70 | VirtIOBalloon *s = VIRTIO_BALLOON(vdev); | |
71 | @@ -526,6 +548,17 @@ static bool virtio_balloon_free_page_support(void *opaque) | |
72 | return virtio_vdev_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT); | |
73 | } | |
74 | ||
75 | +static size_t virtio_balloon_config_size(void *opaque) | |
76 | +{ | |
77 | + VirtIOBalloon *s = opaque; | |
78 | + | |
79 | + if (s->use_large_config) { | |
80 | + return sizeof(struct virtio_balloon_config); | |
81 | + } else { | |
82 | + return offsetof(struct virtio_balloon_config, free_page_report_cmd_id); | |
83 | + } | |
84 | +} | |
85 | + | |
86 | static void virtio_balloon_free_page_start(VirtIOBalloon *s) | |
87 | { | |
88 | VirtIODevice *vdev = VIRTIO_DEVICE(s); | |
89 | @@ -635,7 +668,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data) | |
90 | } | |
91 | ||
92 | trace_virtio_balloon_get_config(config.num_pages, config.actual); | |
93 | - memcpy(config_data, &config, sizeof(struct virtio_balloon_config)); | |
94 | + memcpy(config_data, &config, virtio_balloon_config_size(dev)); | |
95 | } | |
96 | ||
97 | static int build_dimm_list(Object *obj, void *opaque) | |
98 | @@ -679,7 +712,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev, | |
99 | uint32_t oldactual = dev->actual; | |
100 | ram_addr_t vm_ram_size = get_current_ram_size(); | |
101 | ||
102 | - memcpy(&config, config_data, sizeof(struct virtio_balloon_config)); | |
103 | + memcpy(&config, config_data, virtio_balloon_config_size(dev)); | |
104 | dev->actual = le32_to_cpu(config.actual); | |
105 | if (dev->actual != oldactual) { | |
106 | qapi_event_send_balloon_change(vm_ram_size - | |
107 | @@ -766,7 +799,7 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp) | |
108 | int ret; | |
109 | ||
110 | virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON, | |
111 | - sizeof(struct virtio_balloon_config)); | |
112 | + virtio_balloon_config_size(s)); | |
113 | ||
114 | ret = qemu_add_balloon_handler(virtio_balloon_to_target, | |
115 | virtio_balloon_stat, s); | |
116 | @@ -791,7 +824,7 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp) | |
117 | s->free_page_report_notify.notify = | |
118 | virtio_balloon_free_page_report_notify; | |
119 | precopy_add_notifier(&s->free_page_report_notify); | |
120 | - if (s->iothread) { | |
121 | + if (s->iothread && s->use_large_config) { | |
122 | object_ref(OBJECT(s->iothread)); | |
123 | s->free_page_bh = aio_bh_new(iothread_get_aio_context(s->iothread), | |
124 | virtio_ballloon_get_free_page_hints, s); | |
125 | @@ -804,6 +837,11 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp) | |
126 | virtio_error(vdev, "iothread is missing"); | |
127 | } | |
128 | } | |
129 | + | |
130 | + if (!s->use_large_config) { | |
131 | + s->host_features &= ~(1 << VIRTIO_BALLOON_F_PAGE_POISON); | |
132 | + } | |
133 | + | |
134 | reset_stats(s); | |
135 | } | |
136 | ||
137 | @@ -880,6 +918,12 @@ static void virtio_balloon_instance_init(Object *obj) | |
138 | balloon_stats_get_poll_interval, | |
139 | balloon_stats_set_poll_interval, | |
140 | NULL, s, NULL); | |
141 | + | |
142 | + s->use_large_config = true; | |
143 | + object_property_add(obj, "x-use-large-balloon-config", "bool", | |
144 | + balloon_get_large_config, | |
145 | + balloon_set_large_config, | |
146 | + NULL, s, NULL); | |
147 | } | |
148 | ||
149 | static const VMStateDescription vmstate_virtio_balloon = { | |
150 | diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h | |
151 | index 1afafb12f6..f212c08bd7 100644 | |
152 | --- a/include/hw/virtio/virtio-balloon.h | |
153 | +++ b/include/hw/virtio/virtio-balloon.h | |
154 | @@ -45,6 +45,7 @@ enum virtio_balloon_free_page_report_status { | |
155 | typedef struct VirtIOBalloon { | |
156 | VirtIODevice parent_obj; | |
157 | VirtQueue *ivq, *dvq, *svq, *free_page_vq; | |
158 | + bool use_large_config; | |
159 | uint32_t free_page_report_status; | |
160 | uint32_t num_pages; | |
161 | uint32_t actual; |