1 From e9062966428416da41ec5f9ace3d2ef58b3265b1 Mon Sep 17 00:00:00 2001
2 From: Alon Levy <alevy@redhat.com>
3 Date: Wed, 22 Aug 2012 11:16:25 +0300
4 Subject: [PATCH] qxl: add QXL_IO_MONITORS_CONFIG_ASYNC
6 Revision bumped to 4 for new IO support, enabled for spice-server >=
7 0.11.1. New io enabled if revision is 4. Revision can be set to 4.
9 [ kraxel: 3 continues to be the default revision. Once we have a new
10 stable spice-server release and the qemu patches to enable
11 the new bits merged we'll go flip the switch and make rev4
14 This io calls the corresponding new spice api
15 spice_qxl_monitors_config_async to let spice-server read a new guest set
16 monitors config and notify the client.
18 On migration reissue spice_qxl_monitors_config_async.
22 Signed-off-by: Alon Levy <alevy@redhat.com>
23 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
27 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
28 (cherry picked from commit 020af1c45fec664d5d4cf3b8e5117f8bc1d691f2)
34 Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
37 hw/qxl.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
40 ui/spice-display.h | 1 +
41 5 files changed, 111 insertions(+), 3 deletions(-)
43 diff --git a/configure b/configure
44 index 8ffddf4..b5cea26 100755
47 @@ -2670,6 +2670,9 @@ EOF
49 libs_softmmu="$libs_softmmu $spice_libs"
50 QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags"
51 + if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then
52 + spice_qxl_io_monitors_config_async="yes"
55 if test "$spice" = "yes" ; then
56 feature_not_found "spice"
57 @@ -3407,6 +3410,10 @@ if test "$spice" = "yes" ; then
58 echo "CONFIG_SPICE=y" >> $config_host_mak
61 +if test "$spice_qxl_io_monitors_config_async" = "yes" ; then
62 + echo "CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC=y" >> $config_host_mak
65 if test "$smartcard" = "yes" ; then
66 echo "CONFIG_SMARTCARD=y" >> $config_host_mak
68 diff --git a/hw/qxl.c b/hw/qxl.c
69 index baf9bb4..27f3779 100644
76 +#ifndef CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC
77 +/* spice-protocol is too old, add missing definitions */
78 +#define QXL_IO_MONITORS_CONFIG_ASYNC (QXL_IO_FLUSH_RELEASE + 1)
82 * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as
83 * such can be changed by the guest, so to avoid a guest trigerrable
84 @@ -249,6 +254,39 @@ static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
88 +static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay)
90 + trace_qxl_spice_monitors_config(qxl->id);
91 +/* 0x000b01 == 0.11.1 */
92 +#if SPICE_SERVER_VERSION >= 0x000b01 && \
93 + defined(CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC)
96 + * don't use QXL_COOKIE_TYPE_IO:
97 + * - we are not running yet (post_load), we will assert
99 + * - this is not a guest io, but a reply, so async_io isn't set.
101 + spice_qxl_monitors_config_async(&qxl->ssd.qxl,
102 + qxl->guest_monitors_config,
103 + MEMSLOT_GROUP_GUEST,
104 + (uintptr_t)qxl_cookie_new(
105 + QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
108 + qxl->guest_monitors_config = qxl->ram->monitors_config;
109 + spice_qxl_monitors_config_async(&qxl->ssd.qxl,
110 + qxl->ram->monitors_config,
111 + MEMSLOT_GROUP_GUEST,
112 + (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
113 + QXL_IO_MONITORS_CONFIG_ASYNC));
116 + fprintf(stderr, "qxl: too old spice-protocol/spice-server for "
117 + "QXL_IO_MONITORS_CONFIG_ASYNC\n");
121 void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
123 trace_qxl_spice_reset_image_cache(qxl->id);
124 @@ -538,6 +576,7 @@ static const char *io_port_to_string(uint32_t io_port)
125 = "QXL_IO_DESTROY_ALL_SURFACES_ASYNC",
126 [QXL_IO_FLUSH_SURFACES_ASYNC] = "QXL_IO_FLUSH_SURFACES_ASYNC",
127 [QXL_IO_FLUSH_RELEASE] = "QXL_IO_FLUSH_RELEASE",
128 + [QXL_IO_MONITORS_CONFIG_ASYNC] = "QXL_IO_MONITORS_CONFIG_ASYNC",
130 return io_port_to_string[io_port];
132 @@ -819,6 +858,7 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
133 case QXL_IO_DESTROY_PRIMARY_ASYNC:
134 case QXL_IO_UPDATE_AREA_ASYNC:
135 case QXL_IO_FLUSH_SURFACES_ASYNC:
136 + case QXL_IO_MONITORS_CONFIG_ASYNC:
138 case QXL_IO_CREATE_PRIMARY_ASYNC:
139 qxl_create_guest_primary_complete(qxl);
140 @@ -894,6 +934,8 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
141 case QXL_COOKIE_TYPE_RENDER_UPDATE_AREA:
142 qxl_render_update_area_done(qxl, cookie);
144 + case QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG:
147 fprintf(stderr, "qxl: %s: unexpected cookie type %d\n",
148 __func__, cookie->type);
149 @@ -1315,6 +1357,13 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
153 + if (d->revision <= QXL_REVISION_STABLE_V10 &&
154 + io_port >= QXL_IO_FLUSH_SURFACES_ASYNC) {
155 + qxl_set_guest_bug(d, "unsupported io %d for revision %d\n",
156 + io_port, d->revision);
162 case QXL_IO_SET_MODE:
163 @@ -1334,7 +1383,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
164 io_port, io_port_to_string(io_port));
165 /* be nice to buggy guest drivers */
166 if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
167 - io_port <= QXL_IO_DESTROY_ALL_SURFACES_ASYNC) {
168 + io_port < QXL_IO_RANGE_SIZE) {
169 qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
172 @@ -1362,6 +1411,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
173 io_port = QXL_IO_DESTROY_ALL_SURFACES;
175 case QXL_IO_FLUSH_SURFACES_ASYNC:
176 + case QXL_IO_MONITORS_CONFIG_ASYNC:
179 qemu_mutex_lock(&d->async_lock);
180 @@ -1503,6 +1553,9 @@ async_common:
181 d->mode = QXL_MODE_UNDEFINED;
182 qxl_spice_destroy_surfaces(d, async);
184 + case QXL_IO_MONITORS_CONFIG_ASYNC:
185 + qxl_spice_monitors_config_async(d, 0);
188 qxl_set_guest_bug(d, "%s: unexpected ioport=0x%x\n", __func__, io_port);
190 @@ -1798,6 +1851,17 @@ static int qxl_init_common(PCIQXLDevice *qxl)
194 + pci_device_rev = QXL_REVISION_STABLE_V10;
195 + io_size = 32; /* PCI region size must be pow2 */
197 +/* 0x000b01 == 0.11.1 */
198 +#if SPICE_SERVER_VERSION >= 0x000b01 && \
199 + defined(CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC)
200 + case 4: /* qxl-4 */
201 + pci_device_rev = QXL_REVISION_STABLE_V12;
202 + io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
206 pci_device_rev = QXL_DEFAULT_REVISION;
207 io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
208 @@ -1996,7 +2060,9 @@ static int qxl_post_load(void *opaque, int version)
210 qxl_spice_loadvm_commands(d, cmds, out);
213 + if (d->guest_monitors_config) {
214 + qxl_spice_monitors_config_async(d, 1);
217 case QXL_MODE_COMPAT:
218 /* note: no need to call qxl_create_memslots, qxl_set_mode
219 @@ -2009,6 +2075,14 @@ static int qxl_post_load(void *opaque, int version)
221 #define QXL_SAVE_VERSION 21
223 +static bool qxl_monitors_config_needed(void *opaque)
225 + PCIQXLDevice *qxl = opaque;
227 + return qxl->guest_monitors_config != 0;
231 static VMStateDescription qxl_memslot = {
232 .name = "qxl-memslot",
233 .version_id = QXL_SAVE_VERSION,
234 @@ -2039,6 +2113,16 @@ static VMStateDescription qxl_surface = {
238 +static VMStateDescription qxl_vmstate_monitors_config = {
239 + .name = "qxl/monitors-config",
241 + .minimum_version_id = 1,
242 + .fields = (VMStateField[]) {
243 + VMSTATE_UINT64(guest_monitors_config, PCIQXLDevice),
244 + VMSTATE_END_OF_LIST()
248 static VMStateDescription qxl_vmstate = {
250 .version_id = QXL_SAVE_VERSION,
251 @@ -2046,7 +2130,7 @@ static VMStateDescription qxl_vmstate = {
252 .pre_save = qxl_pre_save,
253 .pre_load = qxl_pre_load,
254 .post_load = qxl_post_load,
255 - .fields = (VMStateField []) {
256 + .fields = (VMStateField[]) {
257 VMSTATE_PCI_DEVICE(pci, PCIQXLDevice),
258 VMSTATE_STRUCT(vga, PCIQXLDevice, 0, vmstate_vga_common, VGACommonState),
259 VMSTATE_UINT32(shadow_rom.mode, PCIQXLDevice),
260 @@ -2065,6 +2149,14 @@ static VMStateDescription qxl_vmstate = {
261 VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
262 VMSTATE_END_OF_LIST()
264 + .subsections = (VMStateSubsection[]) {
266 + .vmsd = &qxl_vmstate_monitors_config,
267 + .needed = qxl_monitors_config_needed,
274 static Property qxl_properties[] = {
275 diff --git a/hw/qxl.h b/hw/qxl.h
276 index 172baf6..9cfedb7 100644
279 @@ -71,6 +71,8 @@ typedef struct PCIQXLDevice {
281 QXLPHYSICAL guest_cursor;
283 + QXLPHYSICAL guest_monitors_config;
285 QemuMutex track_lock;
287 /* thread signaling */
288 @@ -128,7 +130,12 @@ typedef struct PCIQXLDevice {
293 +/* spice-server 0.12 is still in development */
294 +#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V12
296 #define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10
300 void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
301 diff --git a/trace-events b/trace-events
302 index 04b0723..8fcbc50 100644
305 @@ -956,6 +956,7 @@ qxl_spice_destroy_surfaces(int qid, int async) "%d async=%d"
306 qxl_spice_destroy_surface_wait_complete(int qid, uint32_t id) "%d sid=%d"
307 qxl_spice_destroy_surface_wait(int qid, uint32_t id, int async) "%d sid=%d async=%d"
308 qxl_spice_flush_surfaces_async(int qid, uint32_t surface_count, uint32_t num_free_res) "%d s#=%d, res#=%d"
309 +qxl_spice_monitors_config(int id) "%d"
310 qxl_spice_loadvm_commands(int qid, void *ext, uint32_t count) "%d ext=%p count=%d"
311 qxl_spice_oom(int qid) "%d"
312 qxl_spice_reset_cursor(int qid) "%d"
313 diff --git a/ui/spice-display.h b/ui/spice-display.h
314 index 672d65e..bcff114 100644
315 --- a/ui/spice-display.h
316 +++ b/ui/spice-display.h
317 @@ -51,6 +51,7 @@ typedef enum qxl_async_io {
320 QXL_COOKIE_TYPE_RENDER_UPDATE_AREA,
321 + QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
324 typedef struct QXLCookie {