Merge branch 'master' into f16

Conflicts:
	qemu.spec
This commit is contained in:
Justin M. Forbes 2011-08-04 15:00:28 -05:00
commit 58c34c6ec3
28 changed files with 2005 additions and 44 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ qemu-kvm-0.13.0-25fdf4a.tar.gz
/qemu-kvm-0.15.0-525e3df.tar.gz
/qemu-kvm-0.15.0-fda1906.tar.gz
/qemu-kvm-0.15.0-59fadcc.tar.gz
/qemu-kvm-0.15.0-0af4922.tar.gz

View File

@ -1,7 +1,7 @@
From 47d0d4d2d16bdbb3e80b6c9a29b9db3f81f1d6fd Mon Sep 17 00:00:00 2001
>From a0ca79b6cb44fea156174f937c7398befe884048 Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 21:57:47 +0100
Subject: [PATCH 01/13] char: Split out tcp socket close code in a separate
Subject: [PATCH 01/25] char: Split out tcp socket close code in a separate
function
Signed-off-by: Amit Shah <amit.shah@redhat.com>
@ -10,10 +10,10 @@ Signed-off-by: Amit Shah <amit.shah@redhat.com>
1 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index dcf7065..1701bdf 100644
index 8e8cf31..5682aea 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1945,6 +1945,21 @@ typedef struct {
@@ -1946,6 +1946,21 @@ typedef struct {
static void tcp_chr_accept(void *opaque);
@ -35,7 +35,7 @@ index dcf7065..1701bdf 100644
static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
TCPCharDriver *s = chr->opaque;
@@ -2095,15 +2110,7 @@ static void tcp_chr_read(void *opaque)
@@ -2096,15 +2111,7 @@ static void tcp_chr_read(void *opaque)
len = s->max_size;
size = tcp_chr_recv(chr, (void *)buf, len);
if (size == 0) {

View File

@ -1,7 +1,7 @@
From ffef9f85d32395989a3c5845dfe34d2110ccb82b Mon Sep 17 00:00:00 2001
>From 7cda5b9b8b24b778751a402f2b5e6b7d716f1800 Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 20:31:45 +0100
Subject: [PATCH 02/13] char: Add a QemuChrHandlers struct to initialise
Subject: [PATCH 02/25] char: Add a QemuChrHandlers struct to initialise
chardev handlers
Instead of passing each handler in the qemu_add_handlers() function,
@ -39,7 +39,7 @@ Signed-off-by: Amit Shah <amit.shah@redhat.com>
27 files changed, 233 insertions(+), 83 deletions(-)
diff --git a/gdbstub.c b/gdbstub.c
index c085a5a..0ff61cb 100644
index 27b0cfa..6639849 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2739,6 +2739,12 @@ static void gdb_sigterm_handler(int signal)
@ -751,7 +751,7 @@ index 157b80a..8eeec7e 100644
fail_syntax:
diff --git a/qemu-char.c b/qemu-char.c
index 1701bdf..1c33828 100644
index 5682aea..52bcc0e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -195,19 +195,26 @@ void qemu_chr_send_event(CharDriverState *s, int event)

View File

@ -1,7 +1,7 @@
From cb93720645e20825259dbb4d2f833b05a98e3062 Mon Sep 17 00:00:00 2001
>From 28a0d9d78a886205765f513be2d522592b9ffd42 Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 20:32:58 +0100
Subject: [PATCH 03/13] iohandlers: Add enable/disable_write_fd_handler()
Subject: [PATCH 03/25] iohandlers: Add enable/disable_write_fd_handler()
functions
These will be used to provide a cleaner API for the nonblocking case.

View File

@ -1,7 +1,7 @@
From 66945912c4bd1bc70f3221288a4e7acc5717b336 Mon Sep 17 00:00:00 2001
>From 7058d42cf3e2fab291bd4c42604ef510a46bebe0 Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 21:41:42 +0100
Subject: [PATCH 04/13] char: Add framework for a 'write unblocked' callback
Subject: [PATCH 04/25] char: Add framework for a 'write unblocked' callback
The char layer can let users know that the driver will block on further
input. For users interested in not blocking, they can assign a function
@ -16,7 +16,7 @@ Signed-off-by: Amit Shah <amit.shah@redhat.com>
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index 1c33828..ec4eb68 100644
index 52bcc0e..bc07b20 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -214,11 +214,14 @@ void qemu_chr_add_handlers(CharDriverState *s,

View File

@ -1,7 +1,7 @@
From 8aab343e17b05abb051105cdb367edb4deef0c60 Mon Sep 17 00:00:00 2001
>From 92303bbcdb1a2877bce80e25836d47056060403d Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 22:00:27 +0100
Subject: [PATCH 05/13] char: Update send_all() to handle nonblocking chardev
Subject: [PATCH 05/25] char: Update send_all() to handle nonblocking chardev
write requests
The send_all function is modified to return to the caller in case the
@ -22,7 +22,7 @@ Signed-off-by: Amit Shah <amit.shah@redhat.com>
3 files changed, 77 insertions(+), 9 deletions(-)
diff --git a/net/socket.c b/net/socket.c
index bc1bf58..a40687a 100644
index 11fe5f3..14706fc 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -56,8 +56,8 @@ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_
@ -37,7 +37,7 @@ index bc1bf58..a40687a 100644
static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size)
diff --git a/qemu-char.c b/qemu-char.c
index ec4eb68..8789627 100644
index bc07b20..5dbf063 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -513,7 +513,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
@ -164,7 +164,7 @@ index ec4eb68..8789627 100644
}
static int pty_chr_read_poll(void *opaque)
@@ -1978,8 +2039,15 @@ static void tcp_closed(void *opaque)
@@ -1979,8 +2040,15 @@ static void tcp_closed(void *opaque)
static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
TCPCharDriver *s = chr->opaque;

View File

@ -1,7 +1,7 @@
From 9a773de6f770bf2f05acca786e14abd79a9f930c Mon Sep 17 00:00:00 2001
>From 569b1773afa2b30ec9c64cc71815d6c499cd02c0 Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 22:02:47 +0100
Subject: [PATCH 06/13] char: Equip the unix/tcp backend to handle nonblocking
Subject: [PATCH 06/25] char: Equip the unix/tcp backend to handle nonblocking
writes#
Now that the infrastructure is in place to return -EAGAIN to callers,
@ -18,7 +18,7 @@ Signed-off-by: Amit Shah <amit.shah@redhat.com>
1 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index 8789627..d811f2a 100644
index 5dbf063..f54ce04 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -106,6 +106,19 @@
@ -41,7 +41,7 @@ index 8789627..d811f2a 100644
static void qemu_chr_event(CharDriverState *s, int event)
{
/* Keep track if the char device is open */
@@ -2308,6 +2321,25 @@ static void tcp_chr_close(CharDriverState *chr)
@@ -2309,6 +2322,25 @@ static void tcp_chr_close(CharDriverState *chr)
qemu_chr_event(chr, CHR_EVENT_CLOSED);
}
@ -67,7 +67,7 @@ index 8789627..d811f2a 100644
static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
{
CharDriverState *chr = NULL;
@@ -2364,6 +2396,8 @@ static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
@@ -2365,6 +2397,8 @@ static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
chr->chr_close = tcp_chr_close;
chr->get_msgfd = tcp_get_msgfd;
chr->chr_add_client = tcp_chr_add_client;

View File

@ -1,7 +1,7 @@
From 7e19009aa497ae5bc2da8dfedb956f8a705698f1 Mon Sep 17 00:00:00 2001
>From edcb78965b9cab18004c30721d46138000a2c810 Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 22:05:10 +0100
Subject: [PATCH 07/13] char: Throttle when host connection is down#
Subject: [PATCH 07/25] char: Throttle when host connection is down#
When the host-side connection goes down, throttle the virtio-serial bus
and later unthrottle when a connection gets established. This helps
@ -20,7 +20,7 @@ Signed-off-by: Amit Shah <amit.shah@redhat.com>
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index d811f2a..111fdc8 100644
index f54ce04..8d39500 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -140,6 +140,9 @@ static void qemu_chr_generic_open_bh(void *opaque)
@ -33,7 +33,7 @@ index d811f2a..111fdc8 100644
qemu_bh_delete(s->bh);
s->bh = NULL;
}
@@ -2059,6 +2062,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
@@ -2060,6 +2063,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
ret = send_all(chr, s->fd, buf, len);
if (ret == -1 && errno == EPIPE) {
tcp_closed(chr);

View File

@ -1,7 +1,7 @@
From badc85629db4d774f3b5b41070474bd5479d5be3 Mon Sep 17 00:00:00 2001
>From 06a1e88d3e4dc55e94da35928686571b56b8f7a4 Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 22:06:41 +0100
Subject: [PATCH 08/13] virtio-console: Enable port throttling when chardev is
Subject: [PATCH 08/25] virtio-console: Enable port throttling when chardev is
slow to consume data
When a chardev indicates it can't accept more data, we tell the

View File

@ -1,7 +1,7 @@
From 433a034b4ee87fe228be4e7f7e4399101d1e33c8 Mon Sep 17 00:00:00 2001
>From faa8f1ed4cb40ce4699882a88650a42ca70f0b6b Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Tue, 22 Mar 2011 12:27:59 +0200
Subject: [PATCH 09/13] spice-qemu-char.c: add throttling
Subject: [PATCH 09/25] spice-qemu-char.c: add throttling
BZ: 672191

View File

@ -1,7 +1,7 @@
From 7735740bd0c9f2d9585c64cc5f975dd03f2a7c11 Mon Sep 17 00:00:00 2001
>From b8af15fd71aa0d0eb0f7df053759eaa85176af46 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Tue, 22 Mar 2011 12:28:00 +0200
Subject: [PATCH 10/13] spice-qemu-char.c: remove intermediate buffer
Subject: [PATCH 10/25] spice-qemu-char.c: remove intermediate buffer
BZ: 672191
upstream: not submitted (explained below)

View File

@ -1,7 +1,7 @@
From 2b797647b4a85a765bfdd8f4539d1fa10daad4fa Mon Sep 17 00:00:00 2001
>From 267e2a453cab2966edd3cbef520351dd4880765c Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 19 Jul 2011 10:56:19 +0200
Subject: [PATCH 11/13] usb-redir: Add flow control support
Subject: [PATCH 11/25] usb-redir: Add flow control support
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---

View File

@ -1,7 +1,7 @@
From 824ab3383370291885f1a18978018a41cfac7ee8 Mon Sep 17 00:00:00 2001
>From eea72a6f70c7b4cf632c3637e12d4689ce6ff0f5 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 21 Jul 2011 16:28:06 +0200
Subject: [PATCH 12/13] usb-redir: Call qemu_chr_guest_open/close
Subject: [PATCH 12/25] usb-redir: Call qemu_chr_guest_open/close
To let the chardev now we're ready start receiving data. This is necessary
with the spicevmc chardev to get it registered with the spice-server.

View File

@ -1,7 +1,7 @@
From 5149f056bd4fbeeb0ce3b850febe213a305a348b Mon Sep 17 00:00:00 2001
>From c79ffc7e3357317bd81f2abefa4743eaf8101a4e Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 21 Jul 2011 15:36:40 +0200
Subject: [PATCH 13/13] spice-qemu-char: Generate chardev open/close events
Subject: [PATCH 13/25] spice-qemu-char: Generate chardev open/close events
Define a state callback and make that generate chardev open/close events when
called by the spice-server.

View File

@ -0,0 +1,323 @@
>From e52026748bb0b6e29f7703cc9fe8f8d6f5f345f8 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 17 Jun 2011 10:34:25 +0200
Subject: [PATCH 14/25] spice: add worker wrapper functions.
Add wrapper functions for all spice worker calls.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl-render.c | 4 +-
hw/qxl.c | 32 +++++++++---------
ui/spice-display.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++---
ui/spice-display.h | 22 ++++++++++++
4 files changed, 129 insertions(+), 24 deletions(-)
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 1316066..bef5f14 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -124,8 +124,8 @@ void qxl_render_update(PCIQXLDevice *qxl)
update.bottom = qxl->guest_primary.surface.height;
memset(dirty, 0, sizeof(dirty));
- qxl->ssd.worker->update_area(qxl->ssd.worker, 0, &update,
- dirty, ARRAY_SIZE(dirty), 1);
+ qemu_spice_update_area(&qxl->ssd, 0, &update,
+ dirty, ARRAY_SIZE(dirty), 1);
for (i = 0; i < ARRAY_SIZE(dirty); i++) {
if (qemu_spice_rect_is_empty(dirty+i)) {
diff --git a/hw/qxl.c b/hw/qxl.c
index a6fb7f0..5deb776 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -684,8 +684,8 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
dprint(d, 1, "%s: start%s\n", __FUNCTION__,
loadvm ? " (loadvm)" : "");
- d->ssd.worker->reset_cursor(d->ssd.worker);
- d->ssd.worker->reset_image_cache(d->ssd.worker);
+ qemu_spice_reset_cursor(&d->ssd);
+ qemu_spice_reset_image_cache(&d->ssd);
qxl_reset_surfaces(d);
qxl_reset_memslots(d);
@@ -790,7 +790,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta)
__FUNCTION__, memslot.slot_id,
memslot.virt_start, memslot.virt_end);
- d->ssd.worker->add_memslot(d->ssd.worker, &memslot);
+ qemu_spice_add_memslot(&d->ssd, &memslot);
d->guest_slots[slot_id].ptr = (void*)memslot.virt_start;
d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start;
d->guest_slots[slot_id].delta = delta;
@@ -800,14 +800,14 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta)
static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id)
{
dprint(d, 1, "%s: slot %d\n", __FUNCTION__, slot_id);
- d->ssd.worker->del_memslot(d->ssd.worker, MEMSLOT_GROUP_HOST, slot_id);
+ qemu_spice_del_memslot(&d->ssd, MEMSLOT_GROUP_HOST, slot_id);
d->guest_slots[slot_id].active = 0;
}
static void qxl_reset_memslots(PCIQXLDevice *d)
{
dprint(d, 1, "%s:\n", __FUNCTION__);
- d->ssd.worker->reset_memslots(d->ssd.worker);
+ qemu_spice_reset_memslots(&d->ssd);
memset(&d->guest_slots, 0, sizeof(d->guest_slots));
}
@@ -815,7 +815,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
{
dprint(d, 1, "%s:\n", __FUNCTION__);
d->mode = QXL_MODE_UNDEFINED;
- d->ssd.worker->destroy_surfaces(d->ssd.worker);
+ qemu_spice_destroy_surfaces(&d->ssd);
memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds));
}
@@ -869,7 +869,7 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm)
qxl->mode = QXL_MODE_NATIVE;
qxl->cmdflags = 0;
- qxl->ssd.worker->create_primary_surface(qxl->ssd.worker, 0, &surface);
+ qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface);
/* for local rendering */
qxl_render_resize(qxl);
@@ -884,7 +884,7 @@ static void qxl_destroy_primary(PCIQXLDevice *d)
dprint(d, 1, "%s\n", __FUNCTION__);
d->mode = QXL_MODE_UNDEFINED;
- d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0);
+ qemu_spice_destroy_primary_surface(&d->ssd, 0);
}
static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
@@ -956,15 +956,15 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
case QXL_IO_UPDATE_AREA:
{
QXLRect update = d->ram->update_area;
- d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface,
- &update, NULL, 0, 0);
+ qemu_spice_update_area(&d->ssd, d->ram->update_surface,
+ &update, NULL, 0, 0);
break;
}
case QXL_IO_NOTIFY_CMD:
- d->ssd.worker->wakeup(d->ssd.worker);
+ qemu_spice_wakeup(&d->ssd);
break;
case QXL_IO_NOTIFY_CURSOR:
- d->ssd.worker->wakeup(d->ssd.worker);
+ qemu_spice_wakeup(&d->ssd);
break;
case QXL_IO_UPDATE_IRQ:
qxl_set_irq(d);
@@ -978,7 +978,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
break;
}
d->oom_running = 1;
- d->ssd.worker->oom(d->ssd.worker);
+ qemu_spice_oom(&d->ssd);
d->oom_running = 0;
break;
case QXL_IO_SET_MODE:
@@ -1016,10 +1016,10 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
qxl_destroy_primary(d);
break;
case QXL_IO_DESTROY_SURFACE_WAIT:
- d->ssd.worker->destroy_surface_wait(d->ssd.worker, val);
+ qemu_spice_destroy_surface_wait(&d->ssd, val);
break;
case QXL_IO_DESTROY_ALL_SURFACES:
- d->ssd.worker->destroy_surfaces(d->ssd.worker);
+ qemu_spice_destroy_surfaces(&d->ssd);
break;
default:
fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port);
@@ -1424,7 +1424,7 @@ static int qxl_post_load(void *opaque, int version)
cmds[out].cmd.type = QXL_CMD_CURSOR;
cmds[out].group_id = MEMSLOT_GROUP_GUEST;
out++;
- d->ssd.worker->loadvm_commands(d->ssd.worker, cmds, out);
+ qemu_spice_loadvm_commands(&d->ssd, cmds, out);
qemu_free(cmds);
break;
diff --git a/ui/spice-display.c b/ui/spice-display.c
index feeee73..1e6a38f 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -62,6 +62,89 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
dest->right = MAX(dest->right, r->right);
}
+
+void qemu_spice_update_area(SimpleSpiceDisplay *ssd, uint32_t surface_id,
+ struct QXLRect *area, struct QXLRect *dirty_rects,
+ uint32_t num_dirty_rects,
+ uint32_t clear_dirty_region)
+{
+ ssd->worker->update_area(ssd->worker, surface_id, area, dirty_rects,
+ num_dirty_rects, clear_dirty_region);
+}
+
+void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot)
+{
+ ssd->worker->add_memslot(ssd->worker, memslot);
+}
+
+void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid)
+{
+ ssd->worker->del_memslot(ssd->worker, gid, sid);
+}
+
+void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
+ QXLDevSurfaceCreate *surface)
+{
+ ssd->worker->create_primary_surface(ssd->worker, id, surface);
+}
+
+void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id)
+{
+ ssd->worker->destroy_primary_surface(ssd->worker, id);
+}
+
+void qemu_spice_destroy_surface_wait(SimpleSpiceDisplay *ssd, uint32_t id)
+{
+ ssd->worker->destroy_surface_wait(ssd->worker, id);
+}
+
+void qemu_spice_loadvm_commands(SimpleSpiceDisplay *ssd,
+ struct QXLCommandExt *ext, uint32_t count)
+{
+ ssd->worker->loadvm_commands(ssd->worker, ext, count);
+}
+
+void qemu_spice_wakeup(SimpleSpiceDisplay *ssd)
+{
+ ssd->worker->wakeup(ssd->worker);
+}
+
+void qemu_spice_oom(SimpleSpiceDisplay *ssd)
+{
+ ssd->worker->oom(ssd->worker);
+}
+
+void qemu_spice_start(SimpleSpiceDisplay *ssd)
+{
+ ssd->worker->start(ssd->worker);
+}
+
+void qemu_spice_stop(SimpleSpiceDisplay *ssd)
+{
+ ssd->worker->stop(ssd->worker);
+}
+
+void qemu_spice_reset_memslots(SimpleSpiceDisplay *ssd)
+{
+ ssd->worker->reset_memslots(ssd->worker);
+}
+
+void qemu_spice_destroy_surfaces(SimpleSpiceDisplay *ssd)
+{
+ ssd->worker->destroy_surfaces(ssd->worker);
+}
+
+void qemu_spice_reset_image_cache(SimpleSpiceDisplay *ssd)
+{
+ ssd->worker->reset_image_cache(ssd->worker);
+}
+
+void qemu_spice_reset_cursor(SimpleSpiceDisplay *ssd)
+{
+ ssd->worker->reset_cursor(ssd->worker);
+}
+
+
static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
{
SimpleSpiceUpdate *update;
@@ -161,7 +244,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd)
memset(&memslot, 0, sizeof(memslot));
memslot.slot_group_id = MEMSLOT_GROUP_HOST;
memslot.virt_end = ~0;
- ssd->worker->add_memslot(ssd->worker, &memslot);
+ qemu_spice_add_memslot(ssd, &memslot);
}
void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
@@ -181,14 +264,14 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
surface.mem = (intptr_t)ssd->buf;
surface.group_id = MEMSLOT_GROUP_HOST;
- ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
+ qemu_spice_create_primary_surface(ssd, 0, &surface);
}
void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
{
dprint(1, "%s:\n", __FUNCTION__);
- ssd->worker->destroy_primary_surface(ssd->worker, 0);
+ qemu_spice_destroy_primary_surface(ssd, 0);
}
void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
@@ -196,9 +279,9 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
SimpleSpiceDisplay *ssd = opaque;
if (running) {
- ssd->worker->start(ssd->worker);
+ qemu_spice_start(ssd);
} else {
- ssd->worker->stop(ssd->worker);
+ qemu_spice_stop(ssd);
}
ssd->running = running;
}
@@ -267,7 +350,7 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
if (ssd->notify) {
ssd->notify = 0;
- ssd->worker->wakeup(ssd->worker);
+ qemu_spice_wakeup(ssd);
dprint(2, "%s: notify\n", __FUNCTION__);
}
}
diff --git a/ui/spice-display.h b/ui/spice-display.h
index 2f95f68..5b06b11 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -80,3 +80,25 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
int x, int y, int w, int h);
void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
+
+void qemu_spice_update_area(SimpleSpiceDisplay *ssd, uint32_t surface_id,
+ struct QXLRect *area, struct QXLRect *dirty_rects,
+ uint32_t num_dirty_rects,
+ uint32_t clear_dirty_region);
+void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot);
+void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid,
+ uint32_t sid);
+void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
+ QXLDevSurfaceCreate *surface);
+void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id);
+void qemu_spice_destroy_surface_wait(SimpleSpiceDisplay *ssd, uint32_t id);
+void qemu_spice_loadvm_commands(SimpleSpiceDisplay *ssd,
+ struct QXLCommandExt *ext, uint32_t count);
+void qemu_spice_wakeup(SimpleSpiceDisplay *ssd);
+void qemu_spice_oom(SimpleSpiceDisplay *ssd);
+void qemu_spice_start(SimpleSpiceDisplay *ssd);
+void qemu_spice_stop(SimpleSpiceDisplay *ssd);
+void qemu_spice_reset_memslots(SimpleSpiceDisplay *ssd);
+void qemu_spice_destroy_surfaces(SimpleSpiceDisplay *ssd);
+void qemu_spice_reset_image_cache(SimpleSpiceDisplay *ssd);
+void qemu_spice_reset_cursor(SimpleSpiceDisplay *ssd);
--
1.7.5.1

View File

@ -0,0 +1,84 @@
>From 1de5cd33d8c1ffa35b5bcdf703d4b097284edda0 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 17 Jun 2011 10:42:25 +0200
Subject: [PATCH 15/25] spice: add qemu_spice_display_init_common
Factor out SimpleSpiceDisplay initialization into
qemu_spice_display_init_common() and call it from
both qxl.c (for vga mode) and spice-display.c
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.c | 7 +------
ui/spice-display.c | 17 +++++++++++------
ui/spice-display.h | 1 +
3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 5deb776..2127fa3 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1315,12 +1315,7 @@ static int qxl_init_primary(PCIDevice *dev)
vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
qxl_hw_screen_dump, qxl_hw_text_update, qxl);
- qxl->ssd.ds = vga->ds;
- qemu_mutex_init(&qxl->ssd.lock);
- qxl->ssd.mouse_x = -1;
- qxl->ssd.mouse_y = -1;
- qxl->ssd.bufsize = (16 * 1024 * 1024);
- qxl->ssd.buf = qemu_malloc(qxl->ssd.bufsize);
+ qemu_spice_display_init_common(&qxl->ssd, vga->ds);
qxl0 = qxl;
register_displaychangelistener(vga->ds, &display_listener);
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 1e6a38f..93e25bf 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -286,6 +286,16 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
ssd->running = running;
}
+void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds)
+{
+ ssd->ds = ds;
+ qemu_mutex_init(&ssd->lock);
+ ssd->mouse_x = -1;
+ ssd->mouse_y = -1;
+ ssd->bufsize = (16 * 1024 * 1024);
+ ssd->buf = qemu_malloc(ssd->bufsize);
+}
+
/* display listener callbacks */
void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
@@ -499,12 +509,7 @@ static DisplayChangeListener display_listener = {
void qemu_spice_display_init(DisplayState *ds)
{
assert(sdpy.ds == NULL);
- sdpy.ds = ds;
- qemu_mutex_init(&sdpy.lock);
- sdpy.mouse_x = -1;
- sdpy.mouse_y = -1;
- sdpy.bufsize = (16 * 1024 * 1024);
- sdpy.buf = qemu_malloc(sdpy.bufsize);
+ qemu_spice_display_init_common(&sdpy, ds);
register_displaychangelistener(ds, &display_listener);
sdpy.qxl.base.sif = &dpy_interface.base;
diff --git a/ui/spice-display.h b/ui/spice-display.h
index 5b06b11..eb7a573 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -75,6 +75,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd);
void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd);
void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd);
void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason);
+void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds);
void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
int x, int y, int w, int h);
--
1.7.5.1

View File

@ -0,0 +1,294 @@
>From b1fef6eecf09404114ca016aa090cffa183d40f1 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Wed, 29 Jun 2011 10:07:52 +0200
Subject: [PATCH 16/25] spice/qxl: move worker wrappers
Move the wrapper functions which are used by qxl only to qxl.c.
Rename them from qemu_spice_* to qxl_spice_*. Also pass in a
qxl state pointer instead of a SimpleSpiceDisplay pointer.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl-render.c | 4 +-
hw/qxl.c | 67 ++++++++++++++++++++++++++++++++++++++++++++-------
hw/qxl.h | 13 ++++++++++
ui/spice-display.c | 46 -----------------------------------
ui/spice-display.h | 12 ---------
5 files changed, 72 insertions(+), 70 deletions(-)
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index bef5f14..60b822d 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -124,8 +124,8 @@ void qxl_render_update(PCIQXLDevice *qxl)
update.bottom = qxl->guest_primary.surface.height;
memset(dirty, 0, sizeof(dirty));
- qemu_spice_update_area(&qxl->ssd, 0, &update,
- dirty, ARRAY_SIZE(dirty), 1);
+ qxl_spice_update_area(qxl, 0, &update,
+ dirty, ARRAY_SIZE(dirty), 1);
for (i = 0; i < ARRAY_SIZE(dirty); i++) {
if (qemu_spice_rect_is_empty(dirty+i)) {
diff --git a/hw/qxl.c b/hw/qxl.c
index 2127fa3..803a364 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -125,6 +125,53 @@ static void qxl_reset_memslots(PCIQXLDevice *d);
static void qxl_reset_surfaces(PCIQXLDevice *d);
static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
+
+void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
+ struct QXLRect *area, struct QXLRect *dirty_rects,
+ uint32_t num_dirty_rects,
+ uint32_t clear_dirty_region)
+{
+ qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area, dirty_rects,
+ num_dirty_rects, clear_dirty_region);
+}
+
+void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id)
+{
+ qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
+}
+
+void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
+ uint32_t count)
+{
+ qxl->ssd.worker->loadvm_commands(qxl->ssd.worker, ext, count);
+}
+
+void qxl_spice_oom(PCIQXLDevice *qxl)
+{
+ qxl->ssd.worker->oom(qxl->ssd.worker);
+}
+
+void qxl_spice_reset_memslots(PCIQXLDevice *qxl)
+{
+ qxl->ssd.worker->reset_memslots(qxl->ssd.worker);
+}
+
+void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl)
+{
+ qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
+}
+
+void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
+{
+ qxl->ssd.worker->reset_image_cache(qxl->ssd.worker);
+}
+
+void qxl_spice_reset_cursor(PCIQXLDevice *qxl)
+{
+ qxl->ssd.worker->reset_cursor(qxl->ssd.worker);
+}
+
+
static inline uint32_t msb_mask(uint32_t val)
{
uint32_t mask;
@@ -684,8 +731,8 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
dprint(d, 1, "%s: start%s\n", __FUNCTION__,
loadvm ? " (loadvm)" : "");
- qemu_spice_reset_cursor(&d->ssd);
- qemu_spice_reset_image_cache(&d->ssd);
+ qxl_spice_reset_cursor(d);
+ qxl_spice_reset_image_cache(d);
qxl_reset_surfaces(d);
qxl_reset_memslots(d);
@@ -807,7 +854,7 @@ static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id)
static void qxl_reset_memslots(PCIQXLDevice *d)
{
dprint(d, 1, "%s:\n", __FUNCTION__);
- qemu_spice_reset_memslots(&d->ssd);
+ qxl_spice_reset_memslots(d);
memset(&d->guest_slots, 0, sizeof(d->guest_slots));
}
@@ -815,7 +862,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
{
dprint(d, 1, "%s:\n", __FUNCTION__);
d->mode = QXL_MODE_UNDEFINED;
- qemu_spice_destroy_surfaces(&d->ssd);
+ qxl_spice_destroy_surfaces(d);
memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds));
}
@@ -956,8 +1003,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
case QXL_IO_UPDATE_AREA:
{
QXLRect update = d->ram->update_area;
- qemu_spice_update_area(&d->ssd, d->ram->update_surface,
- &update, NULL, 0, 0);
+ qxl_spice_update_area(d, d->ram->update_surface,
+ &update, NULL, 0, 0);
break;
}
case QXL_IO_NOTIFY_CMD:
@@ -978,7 +1025,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
break;
}
d->oom_running = 1;
- qemu_spice_oom(&d->ssd);
+ qxl_spice_oom(d);
d->oom_running = 0;
break;
case QXL_IO_SET_MODE:
@@ -1016,10 +1063,10 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
qxl_destroy_primary(d);
break;
case QXL_IO_DESTROY_SURFACE_WAIT:
- qemu_spice_destroy_surface_wait(&d->ssd, val);
+ qxl_spice_destroy_surface_wait(d, val);
break;
case QXL_IO_DESTROY_ALL_SURFACES:
- qemu_spice_destroy_surfaces(&d->ssd);
+ qxl_spice_destroy_surfaces(d);
break;
default:
fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port);
@@ -1419,7 +1466,7 @@ static int qxl_post_load(void *opaque, int version)
cmds[out].cmd.type = QXL_CMD_CURSOR;
cmds[out].group_id = MEMSLOT_GROUP_GUEST;
out++;
- qemu_spice_loadvm_commands(&d->ssd, cmds, out);
+ qxl_spice_loadvm_commands(d, cmds, out);
qemu_free(cmds);
break;
diff --git a/hw/qxl.h b/hw/qxl.h
index f6c450d..e62b9d0 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -98,6 +98,19 @@ typedef struct PCIQXLDevice {
/* qxl.c */
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
+void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
+ struct QXLRect *area, struct QXLRect *dirty_rects,
+ uint32_t num_dirty_rects,
+ uint32_t clear_dirty_region);
+void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id);
+void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
+ uint32_t count);
+void qxl_spice_oom(PCIQXLDevice *qxl);
+void qxl_spice_reset_memslots(PCIQXLDevice *qxl);
+void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl);
+void qxl_spice_reset_image_cache(PCIQXLDevice *qxl);
+void qxl_spice_reset_cursor(PCIQXLDevice *qxl);
+
/* qxl-logger.c */
void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id);
void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 93e25bf..af10ae8 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -63,15 +63,6 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
}
-void qemu_spice_update_area(SimpleSpiceDisplay *ssd, uint32_t surface_id,
- struct QXLRect *area, struct QXLRect *dirty_rects,
- uint32_t num_dirty_rects,
- uint32_t clear_dirty_region)
-{
- ssd->worker->update_area(ssd->worker, surface_id, area, dirty_rects,
- num_dirty_rects, clear_dirty_region);
-}
-
void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot)
{
ssd->worker->add_memslot(ssd->worker, memslot);
@@ -93,27 +84,11 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id)
ssd->worker->destroy_primary_surface(ssd->worker, id);
}
-void qemu_spice_destroy_surface_wait(SimpleSpiceDisplay *ssd, uint32_t id)
-{
- ssd->worker->destroy_surface_wait(ssd->worker, id);
-}
-
-void qemu_spice_loadvm_commands(SimpleSpiceDisplay *ssd,
- struct QXLCommandExt *ext, uint32_t count)
-{
- ssd->worker->loadvm_commands(ssd->worker, ext, count);
-}
-
void qemu_spice_wakeup(SimpleSpiceDisplay *ssd)
{
ssd->worker->wakeup(ssd->worker);
}
-void qemu_spice_oom(SimpleSpiceDisplay *ssd)
-{
- ssd->worker->oom(ssd->worker);
-}
-
void qemu_spice_start(SimpleSpiceDisplay *ssd)
{
ssd->worker->start(ssd->worker);
@@ -124,27 +99,6 @@ void qemu_spice_stop(SimpleSpiceDisplay *ssd)
ssd->worker->stop(ssd->worker);
}
-void qemu_spice_reset_memslots(SimpleSpiceDisplay *ssd)
-{
- ssd->worker->reset_memslots(ssd->worker);
-}
-
-void qemu_spice_destroy_surfaces(SimpleSpiceDisplay *ssd)
-{
- ssd->worker->destroy_surfaces(ssd->worker);
-}
-
-void qemu_spice_reset_image_cache(SimpleSpiceDisplay *ssd)
-{
- ssd->worker->reset_image_cache(ssd->worker);
-}
-
-void qemu_spice_reset_cursor(SimpleSpiceDisplay *ssd)
-{
- ssd->worker->reset_cursor(ssd->worker);
-}
-
-
static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
{
SimpleSpiceUpdate *update;
diff --git a/ui/spice-display.h b/ui/spice-display.h
index eb7a573..abe99c7 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -82,24 +82,12 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
-void qemu_spice_update_area(SimpleSpiceDisplay *ssd, uint32_t surface_id,
- struct QXLRect *area, struct QXLRect *dirty_rects,
- uint32_t num_dirty_rects,
- uint32_t clear_dirty_region);
void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot);
void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid,
uint32_t sid);
void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
QXLDevSurfaceCreate *surface);
void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id);
-void qemu_spice_destroy_surface_wait(SimpleSpiceDisplay *ssd, uint32_t id);
-void qemu_spice_loadvm_commands(SimpleSpiceDisplay *ssd,
- struct QXLCommandExt *ext, uint32_t count);
void qemu_spice_wakeup(SimpleSpiceDisplay *ssd);
-void qemu_spice_oom(SimpleSpiceDisplay *ssd);
void qemu_spice_start(SimpleSpiceDisplay *ssd);
void qemu_spice_stop(SimpleSpiceDisplay *ssd);
-void qemu_spice_reset_memslots(SimpleSpiceDisplay *ssd);
-void qemu_spice_destroy_surfaces(SimpleSpiceDisplay *ssd);
-void qemu_spice_reset_image_cache(SimpleSpiceDisplay *ssd);
-void qemu_spice_reset_cursor(SimpleSpiceDisplay *ssd);
--
1.7.5.1

View File

@ -0,0 +1,92 @@
>From fc1bf5a4be15e71f87fd73f79356a5a1df5aa724 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Wed, 29 Jun 2011 10:24:05 +0200
Subject: [PATCH 17/25] qxl: fix surface tracking & locking
Surface tracking needs proper locking since it is used from vcpu and spice
worker threads, add it. Also reset the surface counter when zapping all
surfaces.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.c | 13 ++++++++++++-
hw/qxl.h | 2 ++
2 files changed, 14 insertions(+), 1 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 803a364..416bd48 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -137,7 +137,12 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id)
{
+ qemu_mutex_lock(&qxl->track_lock);
+ PANIC_ON(id >= NUM_SURFACES);
qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
+ qxl->guest_surfaces.cmds[id] = 0;
+ qxl->guest_surfaces.count--;
+ qemu_mutex_unlock(&qxl->track_lock);
}
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
@@ -158,7 +163,11 @@ void qxl_spice_reset_memslots(PCIQXLDevice *qxl)
void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl)
{
+ qemu_mutex_lock(&qxl->track_lock);
qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
+ memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds));
+ qxl->guest_surfaces.count = 0;
+ qemu_mutex_unlock(&qxl->track_lock);
}
void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
@@ -317,6 +326,7 @@ static void qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext)
QXLSurfaceCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
uint32_t id = le32_to_cpu(cmd->surface_id);
PANIC_ON(id >= NUM_SURFACES);
+ qemu_mutex_lock(&qxl->track_lock);
if (cmd->type == QXL_SURFACE_CMD_CREATE) {
qxl->guest_surfaces.cmds[id] = ext->cmd.data;
qxl->guest_surfaces.count++;
@@ -327,6 +337,7 @@ static void qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext)
qxl->guest_surfaces.cmds[id] = 0;
qxl->guest_surfaces.count--;
}
+ qemu_mutex_unlock(&qxl->track_lock);
break;
}
case QXL_CMD_CURSOR:
@@ -863,7 +874,6 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
dprint(d, 1, "%s:\n", __FUNCTION__);
d->mode = QXL_MODE_UNDEFINED;
qxl_spice_destroy_surfaces(d);
- memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds));
}
/* called from spice server thread context only */
@@ -1283,6 +1293,7 @@ static int qxl_init_common(PCIQXLDevice *qxl)
qxl->generation = 1;
qxl->num_memslots = NUM_MEMSLOTS;
qxl->num_surfaces = NUM_SURFACES;
+ qemu_mutex_init(&qxl->track_lock);
switch (qxl->revision) {
case 1: /* spice 0.4 -- qxl-1 */
diff --git a/hw/qxl.h b/hw/qxl.h
index e62b9d0..5d0e85e 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -55,6 +55,8 @@ typedef struct PCIQXLDevice {
} guest_surfaces;
QXLPHYSICAL guest_cursor;
+ QemuMutex track_lock;
+
/* thread signaling */
pthread_t main;
int pipe[2];
--
1.7.5.1

View File

@ -0,0 +1,71 @@
>From cb29c060e51d2afcd9ba6ed6a115442473381d5a Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Fri, 17 Jun 2011 14:42:09 +0200
Subject: [PATCH 18/25] qxl: add io_port_to_string
Signed-off-by: Alon Levy <alevy@redhat.com>
---
hw/qxl.c | 40 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 39 insertions(+), 1 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 416bd48..6e66021 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -409,6 +409,43 @@ static const char *qxl_mode_to_string(int mode)
return "INVALID";
}
+static const char *io_port_to_string(uint32_t io_port)
+{
+ if (io_port >= QXL_IO_RANGE_SIZE) {
+ return "out of range";
+ }
+ static const char *io_port_to_string[QXL_IO_RANGE_SIZE + 1] = {
+ [QXL_IO_NOTIFY_CMD] = "QXL_IO_NOTIFY_CMD",
+ [QXL_IO_NOTIFY_CURSOR] = "QXL_IO_NOTIFY_CURSOR",
+ [QXL_IO_UPDATE_AREA] = "QXL_IO_UPDATE_AREA",
+ [QXL_IO_UPDATE_IRQ] = "QXL_IO_UPDATE_IRQ",
+ [QXL_IO_NOTIFY_OOM] = "QXL_IO_NOTIFY_OOM",
+ [QXL_IO_RESET] = "QXL_IO_RESET",
+ [QXL_IO_SET_MODE] = "QXL_IO_SET_MODE",
+ [QXL_IO_LOG] = "QXL_IO_LOG",
+ [QXL_IO_MEMSLOT_ADD] = "QXL_IO_MEMSLOT_ADD",
+ [QXL_IO_MEMSLOT_DEL] = "QXL_IO_MEMSLOT_DEL",
+ [QXL_IO_DETACH_PRIMARY] = "QXL_IO_DETACH_PRIMARY",
+ [QXL_IO_ATTACH_PRIMARY] = "QXL_IO_ATTACH_PRIMARY",
+ [QXL_IO_CREATE_PRIMARY] = "QXL_IO_CREATE_PRIMARY",
+ [QXL_IO_DESTROY_PRIMARY] = "QXL_IO_DESTROY_PRIMARY",
+ [QXL_IO_DESTROY_SURFACE_WAIT] = "QXL_IO_DESTROY_SURFACE_WAIT",
+ [QXL_IO_DESTROY_ALL_SURFACES] = "QXL_IO_DESTROY_ALL_SURFACES",
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ [QXL_IO_UPDATE_AREA_ASYNC] = "QXL_IO_UPDATE_AREA_ASYNC",
+ [QXL_IO_MEMSLOT_ADD_ASYNC] = "QXL_IO_MEMSLOT_ADD_ASYNC",
+ [QXL_IO_CREATE_PRIMARY_ASYNC] = "QXL_IO_CREATE_PRIMARY_ASYNC",
+ [QXL_IO_DESTROY_PRIMARY_ASYNC] = "QXL_IO_DESTROY_PRIMARY_ASYNC",
+ [QXL_IO_DESTROY_SURFACE_ASYNC] = "QXL_IO_DESTROY_SURFACE_ASYNC",
+ [QXL_IO_DESTROY_ALL_SURFACES_ASYNC]
+ = "QXL_IO_DESTROY_ALL_SURFACES_ASYNC",
+ [QXL_IO_FLUSH_SURFACES_ASYNC] = "QXL_IO_FLUSH_SURFACES_ASYNC",
+ [QXL_IO_FLUSH_RELEASE] = "QXL_IO_FLUSH_RELEASE",
+#endif
+ };
+ return io_port_to_string[io_port];
+}
+
/* called from spice server thread context only */
static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
{
@@ -1005,7 +1042,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
default:
if (d->mode == QXL_MODE_NATIVE || d->mode == QXL_MODE_COMPAT)
break;
- dprint(d, 1, "%s: unexpected port 0x%x in vga mode\n", __FUNCTION__, io_port);
+ dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n",
+ __func__, io_port, io_port_to_string(io_port));
return;
}
--
1.7.5.1

View File

@ -0,0 +1,110 @@
>From 9e85acc84ed9dbaed1bb7abe83e1b2fe61905706 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Thu, 30 Jun 2011 10:41:36 +0200
Subject: [PATCH 19/25] qxl: error handling fixes and cleanups.
Add qxl_guest_bug() function which is supposed to be called in case
sanity checks of guest requests fail. It raises an error IRQ and
logs a message in case guest debugging is enabled.
Make PANIC_ON() abort instead of exit. That macro should be used
for qemu bugs only, any guest-triggerable stuff should use the new
qxl_guest_bug() function instead.
Convert a few easy cases from PANIC_ON() to qxl_guest_bug() to
show intended usage.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.c | 34 ++++++++++++++++++++++++++++++----
hw/qxl.h | 3 ++-
2 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 6e66021..28c8b5d 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -125,6 +125,16 @@ static void qxl_reset_memslots(PCIQXLDevice *d);
static void qxl_reset_surfaces(PCIQXLDevice *d);
static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
+void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg)
+{
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ qxl_send_events(qxl, QXL_INTERRUPT_ERROR);
+#endif
+ if (qxl->guestdebug) {
+ fprintf(stderr, "qxl-%d: guest bug: %s\n", qxl->id, msg);
+ }
+}
+
void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
struct QXLRect *area, struct QXLRect *dirty_rects,
@@ -1091,22 +1101,38 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
qxl_hard_reset(d, 0);
break;
case QXL_IO_MEMSLOT_ADD:
- PANIC_ON(val >= NUM_MEMSLOTS);
- PANIC_ON(d->guest_slots[val].active);
+ if (val >= NUM_MEMSLOTS) {
+ qxl_guest_bug(d, "QXL_IO_MEMSLOT_ADD: val out of range");
+ break;
+ }
+ if (d->guest_slots[val].active) {
+ qxl_guest_bug(d, "QXL_IO_MEMSLOT_ADD: memory slot already active");
+ break;
+ }
d->guest_slots[val].slot = d->ram->mem_slot;
qxl_add_memslot(d, val, 0);
break;
case QXL_IO_MEMSLOT_DEL:
+ if (val >= NUM_MEMSLOTS) {
+ qxl_guest_bug(d, "QXL_IO_MEMSLOT_DEL: val out of range");
+ break;
+ }
qxl_del_memslot(d, val);
break;
case QXL_IO_CREATE_PRIMARY:
- PANIC_ON(val != 0);
+ if (val != 0) {
+ qxl_guest_bug(d, "QXL_IO_CREATE_PRIMARY: val != 0");
+ break;
+ }
dprint(d, 1, "QXL_IO_CREATE_PRIMARY\n");
d->guest_primary.surface = d->ram->create_surface;
qxl_create_guest_primary(d, 0);
break;
case QXL_IO_DESTROY_PRIMARY:
- PANIC_ON(val != 0);
+ if (val != 0) {
+ qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY: val != 0");
+ break;
+ }
dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (%s)\n", qxl_mode_to_string(d->mode));
qxl_destroy_primary(d);
break;
diff --git a/hw/qxl.h b/hw/qxl.h
index 5d0e85e..5db9aae 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -86,7 +86,7 @@ typedef struct PCIQXLDevice {
#define PANIC_ON(x) if ((x)) { \
printf("%s: PANIC %s failed\n", __FUNCTION__, #x); \
- exit(-1); \
+ abort(); \
}
#define dprint(_qxl, _level, _fmt, ...) \
@@ -99,6 +99,7 @@ typedef struct PCIQXLDevice {
/* qxl.c */
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
+void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg);
void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
struct QXLRect *area, struct QXLRect *dirty_rects,
--
1.7.5.1

View File

@ -0,0 +1,52 @@
>From beffb6d82668c7f8bcead447422529532cc0b4e7 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Wed, 6 Jul 2011 13:40:29 +0200
Subject: [PATCH 20/25] qxl: make qxl_guest_bug take variable arguments
Signed-off-by: Alon Levy <alevy@redhat.com>
---
hw/qxl.c | 9 +++++++--
hw/qxl.h | 2 +-
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 28c8b5d..c50eaf9 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -125,13 +125,18 @@ static void qxl_reset_memslots(PCIQXLDevice *d);
static void qxl_reset_surfaces(PCIQXLDevice *d);
static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
-void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg)
+void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...)
{
#if SPICE_INTERFACE_QXL_MINOR >= 1
qxl_send_events(qxl, QXL_INTERRUPT_ERROR);
#endif
if (qxl->guestdebug) {
- fprintf(stderr, "qxl-%d: guest bug: %s\n", qxl->id, msg);
+ va_list ap;
+ va_start(ap, msg);
+ fprintf(stderr, "qxl-%d: guest bug: ", qxl->id);
+ vfprintf(stderr, msg, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
}
}
diff --git a/hw/qxl.h b/hw/qxl.h
index 5db9aae..32ca5a0 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -99,7 +99,7 @@ typedef struct PCIQXLDevice {
/* qxl.c */
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
-void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg);
+void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...);
void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
struct QXLRect *area, struct QXLRect *dirty_rects,
--
1.7.5.1

View File

@ -0,0 +1,31 @@
>From 4eb9272a4185cf47a4a4e9cb59a95cfd9939e86c Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Wed, 29 Jun 2011 11:53:21 +0200
Subject: [PATCH 21/25] qxl: only disallow specific io's in vga mode
Since the driver is still in operation even after moving to UNDEFINED, i.e.
by destroying primary in any way.
Signed-off-by: Alon Levy <alevy@redhat.com>
---
hw/qxl.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index c50eaf9..23e3240 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1055,8 +1055,9 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
case QXL_IO_LOG:
break;
default:
- if (d->mode == QXL_MODE_NATIVE || d->mode == QXL_MODE_COMPAT)
+ if (d->mode != QXL_MODE_VGA) {
break;
+ }
dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n",
__func__, io_port, io_port_to_string(io_port));
return;
--
1.7.5.1

View File

@ -0,0 +1,659 @@
>From b25a2a169340f70b29d47d0598df1ac525a87bf9 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Thu, 23 Jun 2011 20:02:18 +0200
Subject: [PATCH 22/25] qxl: async io support using new spice api
Some of the QXL port i/o commands are waiting for the spice server to
complete certain actions. Add async versions for these commands, so we
don't block the vcpu while the spice server processses the command.
Instead the qxl device will raise an IRQ when done.
The async command processing relies on an added QXLInterface::async_complete
and added QXLWorker::*_async additions, in spice server qxl >= 3.1
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Alon Levy <alevy@redhat.com>
---
hw/qxl-render.c | 2 +-
hw/qxl.c | 240 ++++++++++++++++++++++++++++++++++++++++++++--------
hw/qxl.h | 16 +++-
ui/spice-display.c | 47 ++++++++--
ui/spice-display.h | 23 +++++-
5 files changed, 274 insertions(+), 54 deletions(-)
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 60b822d..643ff2d 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -125,7 +125,7 @@ void qxl_render_update(PCIQXLDevice *qxl)
memset(dirty, 0, sizeof(dirty));
qxl_spice_update_area(qxl, 0, &update,
- dirty, ARRAY_SIZE(dirty), 1);
+ dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
for (i = 0; i < ARRAY_SIZE(dirty); i++) {
if (qemu_spice_rect_is_empty(dirty+i)) {
diff --git a/hw/qxl.c b/hw/qxl.c
index 23e3240..d3109e4 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -120,7 +120,7 @@ static QXLMode qxl_modes[] = {
static PCIQXLDevice *qxl0;
static void qxl_send_events(PCIQXLDevice *d, uint32_t events);
-static void qxl_destroy_primary(PCIQXLDevice *d);
+static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async);
static void qxl_reset_memslots(PCIQXLDevice *d);
static void qxl_reset_surfaces(PCIQXLDevice *d);
static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
@@ -144,22 +144,47 @@ void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...)
void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
struct QXLRect *area, struct QXLRect *dirty_rects,
uint32_t num_dirty_rects,
- uint32_t clear_dirty_region)
+ uint32_t clear_dirty_region,
+ qxl_async_io async)
{
- qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area, dirty_rects,
- num_dirty_rects, clear_dirty_region);
+ if (async == QXL_SYNC) {
+ qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area,
+ dirty_rects, num_dirty_rects, clear_dirty_region);
+ } else {
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area,
+ clear_dirty_region, 0);
+#else
+ abort();
+#endif
+ }
}
-void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id)
+static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl,
+ uint32_t id)
{
qemu_mutex_lock(&qxl->track_lock);
- PANIC_ON(id >= NUM_SURFACES);
- qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
qxl->guest_surfaces.cmds[id] = 0;
qxl->guest_surfaces.count--;
qemu_mutex_unlock(&qxl->track_lock);
}
+static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
+ qxl_async_io async)
+{
+ if (async) {
+#if SPICE_INTERFACE_QXL_MINOR < 1
+ abort();
+#else
+ spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id,
+ (uint64_t)id);
+#endif
+ } else {
+ qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
+ qxl_spice_destroy_surface_wait_complete(qxl, id);
+ }
+}
+
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
uint32_t count)
{
@@ -176,15 +201,28 @@ void qxl_spice_reset_memslots(PCIQXLDevice *qxl)
qxl->ssd.worker->reset_memslots(qxl->ssd.worker);
}
-void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl)
+static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
{
qemu_mutex_lock(&qxl->track_lock);
- qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds));
qxl->guest_surfaces.count = 0;
qemu_mutex_unlock(&qxl->track_lock);
}
+static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
+{
+ if (async) {
+#if SPICE_INTERFACE_QXL_MINOR < 1
+ abort();
+#else
+ spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl, 0);
+#endif
+ } else {
+ qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
+ qxl_spice_destroy_surfaces_complete(qxl);
+ }
+}
+
void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
{
qxl->ssd.worker->reset_image_cache(qxl->ssd.worker);
@@ -689,6 +727,38 @@ static int interface_flush_resources(QXLInstance *sin)
return ret;
}
+static void qxl_create_guest_primary_complete(PCIQXLDevice *d);
+
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+
+/* called from spice server thread context only */
+static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
+{
+ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+ uint32_t current_async;
+
+ qemu_mutex_lock(&qxl->async_lock);
+ current_async = qxl->current_async;
+ qxl->current_async = QXL_UNDEFINED_IO;
+ qemu_mutex_unlock(&qxl->async_lock);
+
+ dprint(qxl, 2, "async_complete: %d (%ld) done\n", current_async, cookie);
+ switch (current_async) {
+ case QXL_IO_CREATE_PRIMARY_ASYNC:
+ qxl_create_guest_primary_complete(qxl);
+ break;
+ case QXL_IO_DESTROY_ALL_SURFACES_ASYNC:
+ qxl_spice_destroy_surfaces_complete(qxl);
+ break;
+ case QXL_IO_DESTROY_SURFACE_ASYNC:
+ qxl_spice_destroy_surface_wait_complete(qxl, (uint32_t)cookie);
+ break;
+ }
+ qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
+}
+
+#endif
+
static const QXLInterface qxl_interface = {
.base.type = SPICE_INTERFACE_QXL,
.base.description = "qxl gpu",
@@ -708,6 +778,9 @@ static const QXLInterface qxl_interface = {
.req_cursor_notification = interface_req_cursor_notification,
.notify_update = interface_notify_update,
.flush_resources = interface_flush_resources,
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ .async_complete = interface_async_complete,
+#endif
};
static void qxl_enter_vga_mode(PCIQXLDevice *d)
@@ -727,7 +800,7 @@ static void qxl_exit_vga_mode(PCIQXLDevice *d)
return;
}
dprint(d, 1, "%s\n", __FUNCTION__);
- qxl_destroy_primary(d);
+ qxl_destroy_primary(d, QXL_SYNC);
}
static void qxl_set_irq(PCIQXLDevice *d)
@@ -824,13 +897,14 @@ static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
if (qxl->mode != QXL_MODE_VGA) {
dprint(qxl, 1, "%s\n", __FUNCTION__);
- qxl_destroy_primary(qxl);
+ qxl_destroy_primary(qxl, QXL_SYNC);
qxl_soft_reset(qxl);
}
vga_ioport_write(opaque, addr, val);
}
-static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta)
+static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
+ qxl_async_io async)
{
static const int regions[] = {
QXL_RAM_RANGE_INDEX,
@@ -900,7 +974,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta)
__FUNCTION__, memslot.slot_id,
memslot.virt_start, memslot.virt_end);
- qemu_spice_add_memslot(&d->ssd, &memslot);
+ qemu_spice_add_memslot(&d->ssd, &memslot, async);
d->guest_slots[slot_id].ptr = (void*)memslot.virt_start;
d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start;
d->guest_slots[slot_id].delta = delta;
@@ -925,7 +999,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
{
dprint(d, 1, "%s:\n", __FUNCTION__);
d->mode = QXL_MODE_UNDEFINED;
- qxl_spice_destroy_surfaces(d);
+ qxl_spice_destroy_surfaces(d, QXL_SYNC);
}
/* called from spice server thread context only */
@@ -950,7 +1024,14 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
}
}
-static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm)
+static void qxl_create_guest_primary_complete(PCIQXLDevice *qxl)
+{
+ /* for local rendering */
+ qxl_render_resize(qxl);
+}
+
+static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
+ qxl_async_io async)
{
QXLDevSurfaceCreate surface;
QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
@@ -978,22 +1059,26 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm)
qxl->mode = QXL_MODE_NATIVE;
qxl->cmdflags = 0;
- qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface);
+ qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface, async);
- /* for local rendering */
- qxl_render_resize(qxl);
+ if (async == QXL_SYNC) {
+ qxl_create_guest_primary_complete(qxl);
+ }
}
-static void qxl_destroy_primary(PCIQXLDevice *d)
+/* return 1 if surface destoy was initiated (in QXL_ASYNC case) or
+ * done (in QXL_SYNC case), 0 otherwise. */
+static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
{
if (d->mode == QXL_MODE_UNDEFINED) {
- return;
+ return 0;
}
dprint(d, 1, "%s\n", __FUNCTION__);
d->mode = QXL_MODE_UNDEFINED;
- qemu_spice_destroy_primary_surface(&d->ssd, 0);
+ qemu_spice_destroy_primary_surface(&d->ssd, 0, async);
+ return 1;
}
static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
@@ -1023,10 +1108,10 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
}
d->guest_slots[0].slot = slot;
- qxl_add_memslot(d, 0, devmem);
+ qxl_add_memslot(d, 0, devmem, QXL_SYNC);
d->guest_primary.surface = surface;
- qxl_create_guest_primary(d, 0);
+ qxl_create_guest_primary(d, 0, QXL_SYNC);
d->mode = QXL_MODE_COMPAT;
d->cmdflags = QXL_COMMAND_FLAG_COMPAT;
@@ -1044,6 +1129,10 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
PCIQXLDevice *d = opaque;
uint32_t io_port = addr - d->io_base;
+ qxl_async_io async = QXL_SYNC;
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ uint32_t orig_io_port = io_port;
+#endif
switch (io_port) {
case QXL_IO_RESET:
@@ -1053,6 +1142,10 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
case QXL_IO_CREATE_PRIMARY:
case QXL_IO_UPDATE_IRQ:
case QXL_IO_LOG:
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ case QXL_IO_MEMSLOT_ADD_ASYNC:
+ case QXL_IO_CREATE_PRIMARY_ASYNC:
+#endif
break;
default:
if (d->mode != QXL_MODE_VGA) {
@@ -1060,15 +1153,61 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
}
dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n",
__func__, io_port, io_port_to_string(io_port));
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ /* be nice to buggy guest drivers */
+ if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
+ io_port <= QXL_IO_DESTROY_ALL_SURFACES_ASYNC) {
+ qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
+ }
+#endif
return;
}
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ /* we change the io_port to avoid ifdeffery in the main switch */
+ orig_io_port = io_port;
+ switch (io_port) {
+ case QXL_IO_UPDATE_AREA_ASYNC:
+ io_port = QXL_IO_UPDATE_AREA;
+ goto async_common;
+ case QXL_IO_MEMSLOT_ADD_ASYNC:
+ io_port = QXL_IO_MEMSLOT_ADD;
+ goto async_common;
+ case QXL_IO_CREATE_PRIMARY_ASYNC:
+ io_port = QXL_IO_CREATE_PRIMARY;
+ goto async_common;
+ case QXL_IO_DESTROY_PRIMARY_ASYNC:
+ io_port = QXL_IO_DESTROY_PRIMARY;
+ goto async_common;
+ case QXL_IO_DESTROY_SURFACE_ASYNC:
+ io_port = QXL_IO_DESTROY_SURFACE_WAIT;
+ goto async_common;
+ case QXL_IO_DESTROY_ALL_SURFACES_ASYNC:
+ io_port = QXL_IO_DESTROY_ALL_SURFACES;
+async_common:
+ async = QXL_ASYNC;
+ qemu_mutex_lock(&d->async_lock);
+ if (d->current_async != QXL_UNDEFINED_IO) {
+ qxl_guest_bug(d, "%d async started before last (%d) complete",
+ io_port, d->current_async);
+ qemu_mutex_unlock(&d->async_lock);
+ return;
+ }
+ d->current_async = orig_io_port;
+ qemu_mutex_unlock(&d->async_lock);
+ dprint(d, 2, "start async %d (%d)\n", io_port, val);
+ break;
+ default:
+ break;
+ }
+#endif
+
switch (io_port) {
case QXL_IO_UPDATE_AREA:
{
QXLRect update = d->ram->update_area;
qxl_spice_update_area(d, d->ram->update_surface,
- &update, NULL, 0, 0);
+ &update, NULL, 0, 0, async);
break;
}
case QXL_IO_NOTIFY_CMD:
@@ -1116,7 +1255,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
break;
}
d->guest_slots[val].slot = d->ram->mem_slot;
- qxl_add_memslot(d, val, 0);
+ qxl_add_memslot(d, val, 0, async);
break;
case QXL_IO_MEMSLOT_DEL:
if (val >= NUM_MEMSLOTS) {
@@ -1127,31 +1266,56 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
break;
case QXL_IO_CREATE_PRIMARY:
if (val != 0) {
- qxl_guest_bug(d, "QXL_IO_CREATE_PRIMARY: val != 0");
- break;
+ qxl_guest_bug(d, "QXL_IO_CREATE_PRIMARY (async=%d): val != 0",
+ async);
+ goto cancel_async;
}
- dprint(d, 1, "QXL_IO_CREATE_PRIMARY\n");
+ dprint(d, 1, "QXL_IO_CREATE_PRIMARY async=%d\n", async);
d->guest_primary.surface = d->ram->create_surface;
- qxl_create_guest_primary(d, 0);
+ qxl_create_guest_primary(d, 0, async);
break;
case QXL_IO_DESTROY_PRIMARY:
if (val != 0) {
- qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY: val != 0");
- break;
+ qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY (async=%d): val != 0",
+ async);
+ goto cancel_async;
+ }
+ dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (async=%d) (%s)\n", async,
+ qxl_mode_to_string(d->mode));
+ if (!qxl_destroy_primary(d, async)) {
+ dprint(d, 1, "QXL_IO_DESTROY_PRIMARY_ASYNC in %s, ignored\n",
+ qxl_mode_to_string(d->mode));
+ goto cancel_async;
}
- dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (%s)\n", qxl_mode_to_string(d->mode));
- qxl_destroy_primary(d);
break;
case QXL_IO_DESTROY_SURFACE_WAIT:
- qxl_spice_destroy_surface_wait(d, val);
+ if (val >= NUM_SURFACES) {
+ qxl_guest_bug(d, "QXL_IO_DESTROY_SURFACE (async=%d):"
+ "%d >= NUM_SURFACES", async, val);
+ goto cancel_async;
+ }
+ qxl_spice_destroy_surface_wait(d, val, async);
break;
case QXL_IO_DESTROY_ALL_SURFACES:
- qxl_spice_destroy_surfaces(d);
+ d->mode = QXL_MODE_UNDEFINED;
+ qxl_spice_destroy_surfaces(d, async);
break;
default:
fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port);
abort();
}
+ return;
+cancel_async:
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ if (async) {
+ qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
+ qemu_mutex_lock(&d->async_lock);
+ d->current_async = QXL_UNDEFINED_IO;
+ qemu_mutex_unlock(&d->async_lock);
+ }
+#else
+ return;
+#endif
}
static uint32_t ioport_read(void *opaque, uint32_t addr)
@@ -1364,6 +1528,8 @@ static int qxl_init_common(PCIQXLDevice *qxl)
qxl->num_memslots = NUM_MEMSLOTS;
qxl->num_surfaces = NUM_SURFACES;
qemu_mutex_init(&qxl->track_lock);
+ qemu_mutex_init(&qxl->async_lock);
+ qxl->current_async = QXL_UNDEFINED_IO;
switch (qxl->revision) {
case 1: /* spice 0.4 -- qxl-1 */
@@ -1528,9 +1694,9 @@ static int qxl_post_load(void *opaque, int version)
if (!d->guest_slots[i].active) {
continue;
}
- qxl_add_memslot(d, i, 0);
+ qxl_add_memslot(d, i, 0, QXL_SYNC);
}
- qxl_create_guest_primary(d, 1);
+ qxl_create_guest_primary(d, 1, QXL_SYNC);
/* replay surface-create and cursor-set commands */
cmds = qemu_mallocz(sizeof(QXLCommandExt) * (NUM_SURFACES + 1));
diff --git a/hw/qxl.h b/hw/qxl.h
index 32ca5a0..1046205 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -15,6 +15,8 @@ enum qxl_mode {
QXL_MODE_NATIVE,
};
+#define QXL_UNDEFINED_IO UINT32_MAX
+
typedef struct PCIQXLDevice {
PCIDevice pci;
SimpleSpiceDisplay ssd;
@@ -30,6 +32,9 @@ typedef struct PCIQXLDevice {
int32_t num_memslots;
int32_t num_surfaces;
+ uint32_t current_async;
+ QemuMutex async_lock;
+
struct guest_slots {
QXLMemSlot slot;
void *ptr;
@@ -104,13 +109,12 @@ void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...);
void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
struct QXLRect *area, struct QXLRect *dirty_rects,
uint32_t num_dirty_rects,
- uint32_t clear_dirty_region);
-void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id);
+ uint32_t clear_dirty_region,
+ qxl_async_io async);
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
uint32_t count);
void qxl_spice_oom(PCIQXLDevice *qxl);
void qxl_spice_reset_memslots(PCIQXLDevice *qxl);
-void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl);
void qxl_spice_reset_image_cache(PCIQXLDevice *qxl);
void qxl_spice_reset_cursor(PCIQXLDevice *qxl);
@@ -122,3 +126,9 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
void qxl_render_resize(PCIQXLDevice *qxl);
void qxl_render_update(PCIQXLDevice *qxl);
void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+void qxl_spice_update_area_async(PCIQXLDevice *qxl, uint32_t surface_id,
+ struct QXLRect *area,
+ uint32_t clear_dirty_region,
+ int is_vga);
+#endif
diff --git a/ui/spice-display.c b/ui/spice-display.c
index af10ae8..683d454 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -62,10 +62,18 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
dest->right = MAX(dest->right, r->right);
}
-
-void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot)
-{
- ssd->worker->add_memslot(ssd->worker, memslot);
+void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
+ qxl_async_io async)
+{
+ if (async != QXL_SYNC) {
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ spice_qxl_add_memslot_async(&ssd->qxl, memslot, 0);
+#else
+ abort();
+#endif
+ } else {
+ ssd->worker->add_memslot(ssd->worker, memslot);
+ }
}
void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid)
@@ -74,14 +82,33 @@ void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid)
}
void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
- QXLDevSurfaceCreate *surface)
-{
- ssd->worker->create_primary_surface(ssd->worker, id, surface);
+ QXLDevSurfaceCreate *surface,
+ qxl_async_io async)
+{
+ if (async != QXL_SYNC) {
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface, 0);
+#else
+ abort();
+#endif
+ } else {
+ ssd->worker->create_primary_surface(ssd->worker, id, surface);
+ }
}
-void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id)
+
+void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
+ uint32_t id, qxl_async_io async)
{
- ssd->worker->destroy_primary_surface(ssd->worker, id);
+ if (async != QXL_SYNC) {
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ spice_qxl_destroy_primary_surface_async(&ssd->qxl, id, 0);
+#else
+ abort();
+#endif
+ } else {
+ ssd->worker->destroy_primary_surface(ssd->worker, id);
+ }
}
void qemu_spice_wakeup(SimpleSpiceDisplay *ssd)
@@ -198,7 +225,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd)
memset(&memslot, 0, sizeof(memslot));
memslot.slot_group_id = MEMSLOT_GROUP_HOST;
memslot.virt_end = ~0;
- qemu_spice_add_memslot(ssd, &memslot);
+ qemu_spice_add_memslot(ssd, &memslot, QXL_SYNC);
}
void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
@@ -218,14 +245,14 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
surface.mem = (intptr_t)ssd->buf;
surface.group_id = MEMSLOT_GROUP_HOST;
- qemu_spice_create_primary_surface(ssd, 0, &surface);
+ qemu_spice_create_primary_surface(ssd, 0, &surface, QXL_SYNC);
}
void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
{
dprint(1, "%s:\n", __FUNCTION__);
- qemu_spice_destroy_primary_surface(ssd, 0);
+ qemu_spice_destroy_primary_surface(ssd, 0, QXL_SYNC);
}
void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
diff --git a/ui/spice-display.h b/ui/spice-display.h
index abe99c7..1388641 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -33,6 +33,20 @@
#define NUM_SURFACES 1024
+/*
+ * Internal enum to differenciate between options for
+ * io calls that have a sync (old) version and an _async (new)
+ * version:
+ * QXL_SYNC: use the old version
+ * QXL_ASYNC: use the new version and make sure there are no two
+ * happening at the same time. This is used for guest initiated
+ * calls
+ */
+typedef enum qxl_async_io {
+ QXL_SYNC,
+ QXL_ASYNC,
+} qxl_async_io;
+
typedef struct SimpleSpiceDisplay SimpleSpiceDisplay;
typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
@@ -82,12 +96,15 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
-void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot);
+void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
+ qxl_async_io async);
void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid,
uint32_t sid);
void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
- QXLDevSurfaceCreate *surface);
-void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id);
+ QXLDevSurfaceCreate *surface,
+ qxl_async_io async);
+void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
+ uint32_t id, qxl_async_io async);
void qemu_spice_wakeup(SimpleSpiceDisplay *ssd);
void qemu_spice_start(SimpleSpiceDisplay *ssd);
void qemu_spice_stop(SimpleSpiceDisplay *ssd);
--
1.7.5.1

View File

@ -0,0 +1,77 @@
>From b751be42f3da5666bd11d5a0acb20f225d9a4eb9 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Sun, 5 Jun 2011 11:01:48 +0300
Subject: [PATCH 23/25] qxl: add QXL_IO_FLUSH_{SURFACES,RELEASE} for guest
S3&S4 support
Add two new IOs.
QXL_IO_FLUSH_SURFACES - equivalent to update area for all surfaces, used
to reduce vmexits from NumSurfaces to 1 on guest S3, S4 and resolution change (windows
driver implementation is such that this is done on each of those occasions).
QXL_IO_FLUSH_RELEASE - used to ensure anything on last_release is put on the release ring
for the client to free.
Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
Signed-off-by: Alon Levy <alevy@redhat.com>
---
hw/qxl.c | 30 ++++++++++++++++++++++++++++++
1 files changed, 30 insertions(+), 0 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index d3109e4..847a9b8 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -185,6 +185,13 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
}
}
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
+{
+ spice_qxl_flush_surfaces_async(&qxl->ssd.qxl, 0);
+}
+#endif
+
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
uint32_t count)
{
@@ -1184,6 +1191,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
goto async_common;
case QXL_IO_DESTROY_ALL_SURFACES_ASYNC:
io_port = QXL_IO_DESTROY_ALL_SURFACES;
+ goto async_common;
+ case QXL_IO_FLUSH_SURFACES_ASYNC:
async_common:
async = QXL_ASYNC;
qemu_mutex_lock(&d->async_lock);
@@ -1296,6 +1305,27 @@ async_common:
}
qxl_spice_destroy_surface_wait(d, val, async);
break;
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ case QXL_IO_FLUSH_RELEASE: {
+ QXLReleaseRing *ring = &d->ram->release_ring;
+ if (ring->prod - ring->cons + 1 == ring->num_items) {
+ fprintf(stderr,
+ "ERROR: no flush, full release ring [p%d,%dc]\n",
+ ring->prod, ring->cons);
+ }
+ qxl_push_free_res(d, 1 /* flush */);
+ dprint(d, 1, "QXL_IO_FLUSH_RELEASE exit (%s, s#=%d, res#=%d,%p)\n",
+ qxl_mode_to_string(d->mode), d->guest_surfaces.count,
+ d->num_free_res, d->last_release);
+ break;
+ }
+ case QXL_IO_FLUSH_SURFACES_ASYNC:
+ dprint(d, 1, "QXL_IO_FLUSH_SURFACES_ASYNC (%d) (%s, s#=%d, res#=%d)\n",
+ val, qxl_mode_to_string(d->mode), d->guest_surfaces.count,
+ d->num_free_res);
+ qxl_spice_flush_surfaces_async(d);
+ break;
+#endif
case QXL_IO_DESTROY_ALL_SURFACES:
d->mode = QXL_MODE_UNDEFINED;
qxl_spice_destroy_surfaces(d, async);
--
1.7.5.1

View File

@ -0,0 +1,90 @@
>From 37779d77dff7cb73d333a6440cadd1db0638516b Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Wed, 29 Jun 2011 15:51:24 +0200
Subject: [PATCH 24/25] qxl: bump pci rev
Inform guest drivers about the new features I/O commands we have
now (async commands, S3 support) if building with newer spice, i.e.
if SPICE_INTERFACE_QXL_MINOR >= 1.
sneaked in some 81+ column line spliting.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Alon Levy <alevy@redhat.com>
---
hw/qxl.c | 25 ++++++++++++++++++-------
hw/qxl.h | 6 ++++++
2 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 847a9b8..b684608 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1566,9 +1566,14 @@ static int qxl_init_common(PCIQXLDevice *qxl)
pci_device_rev = QXL_REVISION_STABLE_V04;
break;
case 2: /* spice 0.6 -- qxl-2 */
- default:
pci_device_rev = QXL_REVISION_STABLE_V06;
break;
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+ case 3: /* qxl-3 */
+#endif
+ default:
+ pci_device_rev = QXL_DEFAULT_REVISION;
+ break;
}
pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
@@ -1830,9 +1835,12 @@ static PCIDeviceInfo qxl_info_primary = {
.device_id = QXL_DEVICE_ID_STABLE,
.class_id = PCI_CLASS_DISPLAY_VGA,
.qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
- DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024),
- DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2),
+ DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
+ 64 * 1024 * 1024),
+ DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size,
+ 64 * 1024 * 1024),
+ DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
+ QXL_DEFAULT_REVISION),
DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
@@ -1851,9 +1859,12 @@ static PCIDeviceInfo qxl_info_secondary = {
.device_id = QXL_DEVICE_ID_STABLE,
.class_id = PCI_CLASS_DISPLAY_OTHER,
.qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
- DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024),
- DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2),
+ DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
+ 64 * 1024 * 1024),
+ DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size,
+ 64 * 1024 * 1024),
+ DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
+ QXL_DEFAULT_REVISION),
DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
diff --git a/hw/qxl.h b/hw/qxl.h
index 1046205..4bcf7e1 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -102,6 +102,12 @@ typedef struct PCIQXLDevice {
} \
} while (0)
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10
+#else
+#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V06
+#endif
+
/* qxl.c */
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...);
--
1.7.5.1

View File

@ -0,0 +1,50 @@
>From a1f7b1a638423f74a7a8e3e141f760777dcbd1ab Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Thu, 28 Jul 2011 15:08:48 +0300
Subject: [PATCH 25/25] virtio-serial-bus: replay guest_open on migration
When migrating a host with with a spice agent running the mouse becomes
non operational after the migration. This is rhbz #725965.
The problem is that after migration spice doesn't know the guest agent is open.
Spice is just a char dev here. And a chardev cannot query it's device, the
device has to let the chardev know when it is open. Right now after migration
the chardev which is recreated is in it's default state, which assumes the
guest is disconnected.
Char devices carry no information across migration, but the virtio-serial does
already carry the guest_connected state. This patch passes that bit to the
chardev.
Signed-off-by: Alon Levy <alevy@redhat.com>
---
hw/virtio-serial-bus.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index c5eb931..4a6d932 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -618,6 +618,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
for (i = 0; i < nr_active_ports; i++) {
uint32_t id;
bool host_connected;
+ VirtIOSerialPortInfo *info;
id = qemu_get_be32(f);
port = find_port_by_id(s, id);
@@ -626,6 +627,11 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
}
port->guest_connected = qemu_get_byte(f);
+ info = DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info);
+ if (port->guest_connected && info->guest_open) {
+ /* replay guest open */
+ info->guest_open(port);
+ }
host_connected = qemu_get_byte(f);
if (host_connected != port->host_connected) {
/*
--
1.7.5.1

View File

@ -1,9 +1,9 @@
%define githead 59fadcc
%define githead 0af4922
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 0.15.0
Release: 0.3.20110728%githead%{?dist}
Release: 0.3.20110804%githead%{?dist}
# Epoch because we pushed a qemu-1.0 package
Epoch: 2
License: GPLv2+ and LGPLv2+ and BSD
@ -22,7 +22,7 @@ URL: http://www.qemu.org/
# Source0: http://downloads.sourceforge.net/sourceforge/kvm/qemu-kvm-%{version}.tar.gz
# The source for this package was pulled from upstream's git. Use the
# following commands to generate the tarball:
# git archive --format=tar --prefix=qemu-kvm-0.15.0/ 59fadcc | gzip > qemu-kvm-0.15.0-59fadcc.tar.gz
# git archive --format=tar --prefix=qemu-kvm-0.15.0/ 0af4922 | gzip > qemu-kvm-0.15.0-0af4922.tar.gz
Source0: qemu-kvm-%{version}-%{githead}.tar.gz
Source1: qemu.init
@ -54,6 +54,18 @@ Patch10: 0010-spice-qemu-char.c-remove-intermediate-buffer.patch
Patch11: 0011-usb-redir-Add-flow-control-support.patch
Patch12: 0012-usb-redir-Call-qemu_chr_guest_open-close.patch
Patch13: 0013-spice-qemu-char-Generate-chardev-open-close-events.patch
Patch14: 0014-spice-add-worker-wrapper-functions.patch
Patch15: 0015-spice-add-qemu_spice_display_init_common.patch
Patch16: 0016-spice-qxl-move-worker-wrappers.patch
Patch17: 0017-qxl-fix-surface-tracking-locking.patch
Patch18: 0018-qxl-add-io_port_to_string.patch
Patch19: 0019-qxl-error-handling-fixes-and-cleanups.patch
Patch20: 0020-qxl-make-qxl_guest_bug-take-variable-arguments.patch
Patch21: 0021-qxl-only-disallow-specific-io-s-in-vga-mode.patch
Patch22: 0022-qxl-async-io-support-using-new-spice-api.patch
Patch23: 0023-qxl-add-QXL_IO_FLUSH_-SURFACES-RELEASE-for-guest-S3-.patch
Patch24: 0024-qxl-bump-pci-rev.patch
Patch25: 0025-virtio-serial-bus-replay-guest_open-on-migration.patch
# Fix for default accelerator in non-KVM builds
Patch100: qemu-kvm-default-accelerator.patch
@ -243,6 +255,18 @@ such as kvm_stat.
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch100 -p1
@ -555,6 +579,9 @@ fi
%{_mandir}/man1/qemu-img.1*
%changelog
* Thu Aug 04 2011 Justin M. Forbes <jforbes@redhat.com> - 2:0.15.0-0.3.201108040af4922
- Update to 0.15.0-rc1 as we prepare for 0.15.0 release
* Thu Aug 4 2011 Daniel P. Berrange <berrange@redhat.com> - 2:0.15.0-0.3.2011072859fadcc
- Fix default accelerator for non-KVM builds (rhbz #724814)

View File

@ -1 +1 @@
b0d29c5405ec451421d98d335762ff7c qemu-kvm-0.15.0-59fadcc.tar.gz
a6d16b7d6acfa94300586eda5e7c19a3 qemu-kvm-0.15.0-0af4922.tar.gz