Add a couple of backported QXL/Spice bugfixes

- Add spice volume control patches
This commit is contained in:
Hans de Goede 2012-04-19 17:28:17 +02:00
parent c7f7fc0b56
commit 56753ff081
45 changed files with 5219 additions and 2 deletions

View File

@ -0,0 +1,36 @@
From 4c245e5ecbc7d5c30c8e8bb4bfcd18c79fafddfe Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 3 Apr 2012 14:04:31 +0200
Subject: [PATCH 147/181] usb-ehci: Ensure frindex writes leave a valid
frindex value
frindex is a 14 bits counter, so bits 31-14 should always be 0, and
after the commit titled "usb-ehci: frindex always is a 14 bits counter"
we rely on frindex always being a multiple of 8. I've not seen this in
practice, but theoretically a guest can write a value >= 0x4000 or a value
which is not a multiple of 8 value to frindex, this patch ensures that
things will still work when that happens.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index ff69587..16e6053 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1081,6 +1081,10 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
val &= USBINTR_MASK;
break;
+ case FRINDEX:
+ val &= 0x00003ff8; /* frindex is 14bits and always a multiple of 8 */
+ break;
+
case CONFIGFLAG:
val &= 0x1;
if (val) {
--
1.7.10

View File

@ -0,0 +1,30 @@
From 8858b6d0dac346d9f841cfa84f57cb03bffdf050 Mon Sep 17 00:00:00 2001
From: Markus Armbruster <armbru@redhat.com>
Date: Fri, 4 Nov 2011 10:34:24 +0100
Subject: [PATCH 401/434] qxl: Slot sanity check in qxl_phys2virt() is off by
one, fix
Spotted by Coverity.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 41500e9..e0f9d4a 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1020,7 +1020,7 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
case MEMSLOT_GROUP_HOST:
return (void*)offset;
case MEMSLOT_GROUP_GUEST:
- PANIC_ON(slot > NUM_MEMSLOTS);
+ PANIC_ON(slot >= NUM_MEMSLOTS);
PANIC_ON(!qxl->guest_slots[slot].active);
PANIC_ON(offset < qxl->guest_slots[slot].delta);
offset -= qxl->guest_slots[slot].delta;
--
1.7.10

View File

@ -0,0 +1,45 @@
From f87b93c3944652f90e2c0010da6ee8c182382369 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Wed, 15 Feb 2012 09:15:37 +0100
Subject: [PATCH 402/434] input: send kbd+mouse events only to running guests.
Trying to interact with a stopped guest will queue up the events,
then send them all at once when the guest continues running, with
a high chance to have them cause unwanted actions.
Avoid that by only injecting the input events only when the guest
is in running state.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
input.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/input.c b/input.c
index 9ade63f..b48408d 100644
--- a/input.c
+++ b/input.c
@@ -130,6 +130,9 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
void kbd_put_keycode(int keycode)
{
+ if (!runstate_is_running()) {
+ return;
+ }
if (qemu_put_kbd_event) {
qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
}
@@ -151,6 +154,9 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
void *mouse_event_opaque;
int width, height;
+ if (!runstate_is_running()) {
+ return;
+ }
if (QTAILQ_EMPTY(&mouse_handlers)) {
return;
}
--
1.7.10

View File

@ -0,0 +1,45 @@
From 3b36dd31d54b24e02493fdd86269ba5286086c98 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Wed, 8 Feb 2012 15:58:35 +0100
Subject: [PATCH 403/434] qxl: fix warnings on 32bit
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index e0f9d4a..4fd5e4e 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -628,7 +628,7 @@ static void interface_release_resource(QXLInstance *sin,
if (ext.group_id == MEMSLOT_GROUP_HOST) {
/* host group -> vga mode update request */
- qemu_spice_destroy_update(&qxl->ssd, (void*)ext.info->id);
+ qemu_spice_destroy_update(&qxl->ssd, (void *)(intptr_t)ext.info->id);
return;
}
@@ -751,7 +751,8 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
qxl->current_async = QXL_UNDEFINED_IO;
qemu_mutex_unlock(&qxl->async_lock);
- dprint(qxl, 2, "async_complete: %d (%ld) done\n", current_async, cookie);
+ dprint(qxl, 2, "async_complete: %d (%" PRId64 ") done\n",
+ current_async, cookie);
switch (current_async) {
case QXL_IO_CREATE_PRIMARY_ASYNC:
qxl_create_guest_primary_complete(qxl);
@@ -1018,7 +1019,7 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
switch (group_id) {
case MEMSLOT_GROUP_HOST:
- return (void*)offset;
+ return (void *)(intptr_t)offset;
case MEMSLOT_GROUP_GUEST:
PANIC_ON(slot >= NUM_MEMSLOTS);
PANIC_ON(!qxl->guest_slots[slot].active);
--
1.7.10

View File

@ -0,0 +1,56 @@
From 29fdb0f3a401e5590e465a0cc37d82383f3d5f07 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Wed, 15 Feb 2012 14:04:44 +0100
Subject: [PATCH 404/434] qxl: don't render stuff when the vm is stopped.
This patch fixes the local qxl renderer to not kick spice-server
in case the vm is stopped. First it is largely pointless because
we ask spice-server to process all not-yet processed commands when
the vm is stopped, so there isn't much do do anyway. Second we
avoid triggering an assert in spice-server.
The patch makes sure we still honor redraw requests, even if we don't
ask spice-server for updates. This is needed to handle displaysurface
changes with a stopped vm correctly.
With this patch applied it is possible to take screen shots (via
screendump monitor command) from a qxl gpu even in case the guest
is stopped.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl-render.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 2c51ba9..a7891b2 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -121,19 +121,17 @@ void qxl_render_update(PCIQXLDevice *qxl)
dpy_resize(vga->ds);
}
- if (!qxl->guest_primary.commands) {
- return;
- }
- qxl->guest_primary.commands = 0;
-
update.left = 0;
update.right = qxl->guest_primary.surface.width;
update.top = 0;
update.bottom = qxl->guest_primary.surface.height;
memset(dirty, 0, sizeof(dirty));
- qxl_spice_update_area(qxl, 0, &update,
- dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
+ if (runstate_is_running() && qxl->guest_primary.commands) {
+ qxl->guest_primary.commands = 0;
+ qxl_spice_update_area(qxl, 0, &update,
+ dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
+ }
if (redraw) {
memset(dirty, 0, sizeof(dirty));
dirty[0] = update;
--
1.7.10

View File

@ -0,0 +1,97 @@
From 0386bf2be16745ce87f35ce65153ef4e11f93b22 Mon Sep 17 00:00:00 2001
From: Yonit Halperin <yhalperi@redhat.com>
Date: Wed, 15 Feb 2012 11:22:15 +0200
Subject: [PATCH 405/434] qxl: set only off-screen surfaces dirty instead of
the whole vram
We used to assure the guest surfaces were saved before migration by
setting the whole vram dirty. This patch sets dirty only the areas
that are actually used in the vram.
Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.c | 53 ++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 44 insertions(+), 9 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 4fd5e4e..3d9b1b3 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1010,7 +1010,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
qxl_spice_destroy_surfaces(d, QXL_SYNC);
}
-/* called from spice server thread context only */
+/* can be also called from spice server thread context */
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
{
uint64_t phys = le64_to_cpu(pqxl);
@@ -1469,6 +1469,46 @@ static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
}
}
+static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
+{
+ intptr_t vram_start;
+ int i;
+
+ if (qxl->mode != QXL_MODE_NATIVE) {
+ return;
+ }
+
+ /* dirty the primary surface */
+ qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
+ qxl->shadow_rom.surface0_area_size);
+
+ vram_start = (intptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
+
+ /* dirty the off-screen surfaces */
+ for (i = 0; i < NUM_SURFACES; i++) {
+ QXLSurfaceCmd *cmd;
+ intptr_t surface_offset;
+ int surface_size;
+
+ if (qxl->guest_surfaces.cmds[i] == 0) {
+ continue;
+ }
+
+ cmd = qxl_phys2virt(qxl, qxl->guest_surfaces.cmds[i],
+ MEMSLOT_GROUP_GUEST);
+ assert(cmd->type == QXL_SURFACE_CMD_CREATE);
+ surface_offset = (intptr_t)qxl_phys2virt(qxl,
+ cmd->u.surface_create.data,
+ MEMSLOT_GROUP_GUEST);
+ surface_offset -= vram_start;
+ surface_size = cmd->u.surface_create.height *
+ abs(cmd->u.surface_create.stride);
+ dprint(qxl, 3, "%s: dirty surface %d, offset %d, size %d\n", __func__,
+ i, (int)surface_offset, surface_size);
+ qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
+ }
+}
+
static void qxl_vm_change_state_handler(void *opaque, int running,
RunState state)
{
@@ -1482,14 +1522,9 @@ static void qxl_vm_change_state_handler(void *opaque, int running,
* called
*/
qxl_update_irq(qxl);
- } else if (qxl->mode == QXL_MODE_NATIVE) {
- /* dirty all vram (which holds surfaces) and devram (primary surface)
- * to make sure they are saved */
- /* FIXME #1: should go out during "live" stage */
- /* FIXME #2: we only need to save the areas which are actually used */
- qxl_set_dirty(&qxl->vram_bar, 0, qxl->vram_size);
- qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
- qxl->shadow_rom.surface0_area_size);
+ } else {
+ /* make sure surfaces are saved before migration */
+ qxl_dirty_surfaces(qxl);
}
}
--
1.7.10

View File

@ -0,0 +1,30 @@
From ba922e5e6a5687f13def623e36bfb834ece2defc Mon Sep 17 00:00:00 2001
From: Yonit Halperin <yhalperi@redhat.com>
Date: Wed, 15 Feb 2012 11:22:16 +0200
Subject: [PATCH 406/434] qxl: make sure primary surface is saved on migration
also in compat mode
RHBZ #790083
Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 3d9b1b3..b910337 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1474,7 +1474,7 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
intptr_t vram_start;
int i;
- if (qxl->mode != QXL_MODE_NATIVE) {
+ if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) {
return;
}
--
1.7.10

View File

@ -0,0 +1,139 @@
From 9ada192cfea65a92a765c6a2f6b56a08f1b865df Mon Sep 17 00:00:00 2001
From: "Daniel P. Berrange" <berrange@redhat.com>
Date: Mon, 13 Feb 2012 13:43:08 +0000
Subject: [PATCH 407/434] Add SPICE support to add_client monitor command
With the acceptance of some new APIs to libspice-server.so it
is possible to add support for SPICE to the 'add_client'
monitor command, bringing parity with VNC. Since SPICE can
use TLS or plain connections, the command also gains a new
'tls' parameter to specify whether TLS should be attempted
on the injected client sockets.
This new feature is only enabled if building against a
libspice-server >= 0.10.1
* qmp-commands.hx: Add 'tls' parameter & missing doc for
'skipauth' parameter
* monitor.c: Wire up SPICE for 'add_client' command
* ui/qemu-spice.h, ui/spice-core.c: Add qemu_spice_display_add_client
API to wire up from monitor
[1] http://cgit.freedesktop.org/spice/spice/commit/server/spice.h?id=d55b68b6b44f2499278fa860fb47ff22f5011faa
http://cgit.freedesktop.org/spice/spice/commit/server/spice.h?id=bd07dde530d9504e1cfe7ed5837fc00c26f36716
Changes in v3:
- Added 'optional' flag to new parameters documented
- Added no-op impl of qemu_spice_display_add_client when
SPICE is disabled during build
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
monitor.c | 9 +++++++--
qmp-commands.hx | 6 ++++--
ui/qemu-spice.h | 7 +++++++
ui/spice-core.c | 13 +++++++++++++
4 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/monitor.c b/monitor.c
index a82fda3..3c23aa4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -998,13 +998,18 @@ static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d
CharDriverState *s;
if (strcmp(protocol, "spice") == 0) {
+ int fd = monitor_get_fd(mon, fdname);
+ int skipauth = qdict_get_try_bool(qdict, "skipauth", 0);
+ int tls = qdict_get_try_bool(qdict, "tls", 0);
if (!using_spice) {
/* correct one? spice isn't a device ,,, */
qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
return -1;
}
- qerror_report(QERR_ADD_CLIENT_FAILED);
- return -1;
+ if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) {
+ close(fd);
+ }
+ return 0;
#ifdef CONFIG_VNC
} else if (strcmp(protocol, "vnc") == 0) {
int fd = monitor_get_fd(mon, fdname);
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 97975a5..122b10d 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -909,8 +909,8 @@ EQMP
{
.name = "add_client",
- .args_type = "protocol:s,fdname:s,skipauth:b?",
- .params = "protocol fdname skipauth",
+ .args_type = "protocol:s,fdname:s,skipauth:b?,tls:b?",
+ .params = "protocol fdname skipauth tls",
.help = "add a graphics client",
.user_print = monitor_user_noop,
.mhandler.cmd_new = add_graphics_client,
@@ -926,6 +926,8 @@ Arguments:
- "protocol": protocol name (json-string)
- "fdname": file descriptor name (json-string)
+- "skipauth": whether to skip authentication (json-bool, optional)
+- "tls": whether to perform TLS (json-bool, optional)
Example:
diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h
index c35b29c..680206a 100644
--- a/ui/qemu-spice.h
+++ b/ui/qemu-spice.h
@@ -33,6 +33,7 @@ void qemu_spice_init(void);
void qemu_spice_input_init(void);
void qemu_spice_audio_init(void);
void qemu_spice_display_init(DisplayState *ds);
+int qemu_spice_display_add_client(int csock, int skipauth, int tls);
int qemu_spice_add_interface(SpiceBaseInstance *sin);
int qemu_spice_set_passwd(const char *passwd,
bool fail_if_connected, bool disconnect_if_connected);
@@ -68,6 +69,12 @@ static inline int qemu_spice_migrate_info(const char *h, int p, int t,
return -1;
}
+static inline int qemu_spice_display_add_client(int csock, int skipauth,
+ int tls)
+{
+ return -1;
+}
+
#endif /* CONFIG_SPICE */
#endif /* QEMU_SPICE_H */
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 5639c6f..d98863e 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -747,6 +747,19 @@ int qemu_spice_set_pw_expire(time_t expires)
return qemu_spice_set_ticket(false, false);
}
+int qemu_spice_display_add_client(int csock, int skipauth, int tls)
+{
+#if SPICE_SERVER_VERSION >= 0x000a01
+ if (tls) {
+ return spice_server_add_ssl_client(spice_server, csock, skipauth);
+ } else {
+ return spice_server_add_client(spice_server, csock, skipauth);
+ }
+#else
+ return -1;
+#endif
+}
+
static void spice_register_config(void)
{
qemu_add_opts(&qemu_spice_opts);
--
1.7.10

View File

@ -0,0 +1,83 @@
From 6594551ebe427cae4298b038be02ddc9c335219f Mon Sep 17 00:00:00 2001
From: Yonit Halperin <yhalperi@redhat.com>
Date: Wed, 8 Feb 2012 15:40:15 +0200
Subject: [PATCH 408/434] spice: support ipv6 channel address in monitor
events and in spice info
RHBZ #788444
CC: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
ui/spice-core.c | 37 ++++++++++++++++++++++++++++++++-----
1 file changed, 32 insertions(+), 5 deletions(-)
diff --git a/ui/spice-core.c b/ui/spice-core.c
index d98863e..27216e9 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -220,10 +220,23 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
}
client = qdict_new();
- add_addr_info(client, &info->paddr, info->plen);
-
server = qdict_new();
- add_addr_info(server, &info->laddr, info->llen);
+
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
+ if (info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
+ add_addr_info(client, (struct sockaddr *)&info->paddr_ext,
+ info->plen_ext);
+ add_addr_info(server, (struct sockaddr *)&info->laddr_ext,
+ info->llen_ext);
+ } else {
+ fprintf(stderr, "spice: %s, extended address is expected\n",
+ __func__);
+#endif
+ add_addr_info(client, &info->paddr, info->plen);
+ add_addr_info(server, &info->laddr, info->llen);
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
+ }
+#endif
if (event == SPICE_CHANNEL_EVENT_INITIALIZED) {
qdict_put(server, "auth", qstring_from_str(auth));
@@ -376,16 +389,30 @@ static SpiceChannelList *qmp_query_spice_channels(void)
QTAILQ_FOREACH(item, &channel_list, link) {
SpiceChannelList *chan;
char host[NI_MAXHOST], port[NI_MAXSERV];
+ struct sockaddr *paddr;
+ socklen_t plen;
chan = g_malloc0(sizeof(*chan));
chan->value = g_malloc0(sizeof(*chan->value));
- getnameinfo(&item->info->paddr, item->info->plen,
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
+ if (item->info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
+ paddr = (struct sockaddr *)&item->info->paddr_ext;
+ plen = item->info->plen_ext;
+ } else {
+#endif
+ paddr = &item->info->paddr;
+ plen = item->info->plen;
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
+ }
+#endif
+
+ getnameinfo(paddr, plen,
host, sizeof(host), port, sizeof(port),
NI_NUMERICHOST | NI_NUMERICSERV);
chan->value->host = g_strdup(host);
chan->value->port = g_strdup(port);
- chan->value->family = g_strdup(inet_strfamily(item->info->paddr.sa_family));
+ chan->value->family = g_strdup(inet_strfamily(paddr->sa_family));
chan->value->connection_id = item->info->connection_id;
chan->value->channel_type = item->info->type;
--
1.7.10

View File

@ -0,0 +1,30 @@
From f7656005900f3c07450303afa66151b6a1bb9599 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 17 Feb 2012 14:40:01 +0100
Subject: [PATCH 409/434] qxl: drop vram bar minimum size
There is no reason to require a minimum size of 16 MB for the vram.
Lower the limit to 4096 (one page). Make it disapper completely would
break guests.
---
hw/qxl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index b910337..d71c94d 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1595,8 +1595,8 @@ static int qxl_init_common(PCIQXLDevice *qxl)
init_qxl_rom(qxl);
init_qxl_ram(qxl);
- if (qxl->vram_size < 16 * 1024 * 1024) {
- qxl->vram_size = 16 * 1024 * 1024;
+ if (qxl->vram_size < 4096) {
+ qxl->vram_size = 4096;
}
if (qxl->revision == 1) {
qxl->vram_size = 4096;
--
1.7.10

View File

@ -0,0 +1,97 @@
From 619c68418809149d56025e5b4e7a9828eef90ea8 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 17 Feb 2012 15:02:40 +0100
Subject: [PATCH 410/434] qxl: move ram size init to new function
Factor memory bar sizing bits out to a separate function.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Conflicts:
hw/qxl.c
---
hw/qxl.c | 41 ++++++++++++++++++++++-------------------
1 file changed, 22 insertions(+), 19 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index d71c94d..df8efbc 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1557,6 +1557,25 @@ static DisplayChangeListener display_listener = {
.dpy_refresh = display_refresh,
};
+static void qxl_init_ramsize(PCIQXLDevice *qxl, uint32_t ram_min_mb)
+{
+ /* vga ram (bar 0) */
+ if (qxl->vga.vram_size < ram_min_mb * 1024 * 1024) {
+ qxl->vga.vram_size = ram_min_mb * 1024 * 1024;
+ }
+
+ /* vram (surfaces, bar 1) */
+ if (qxl->vram_size < 4096) {
+ qxl->vram_size = 4096;
+ }
+ if (qxl->revision == 1) {
+ qxl->vram_size = 4096;
+ }
+
+ qxl->vga.vram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
+ qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
+}
+
static int qxl_init_common(PCIQXLDevice *qxl)
{
uint8_t* config = qxl->pci.config;
@@ -1595,13 +1614,6 @@ static int qxl_init_common(PCIQXLDevice *qxl)
init_qxl_rom(qxl);
init_qxl_ram(qxl);
- if (qxl->vram_size < 4096) {
- qxl->vram_size = 4096;
- }
- if (qxl->revision == 1) {
- qxl->vram_size = 4096;
- }
- qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
memory_region_init_ram(&qxl->vram_bar, &qxl->pci.qdev, "qxl.vram",
qxl->vram_size);
@@ -1644,15 +1656,11 @@ static int qxl_init_primary(PCIDevice *dev)
{
PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
VGACommonState *vga = &qxl->vga;
- ram_addr_t ram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
PortioList *qxl_vga_port_list = g_new(PortioList, 1);
qxl->id = 0;
-
- if (ram_size < 32 * 1024 * 1024) {
- ram_size = 32 * 1024 * 1024;
- }
- vga_common_init(vga, ram_size);
+ qxl_init_ramsize(qxl, 32);
+ vga_common_init(vga, qxl->vga.vram_size);
vga_init(vga, pci_address_space(dev), pci_address_space_io(dev), false);
portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga");
portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
@@ -1671,14 +1679,9 @@ static int qxl_init_secondary(PCIDevice *dev)
{
static int device_id = 1;
PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
- ram_addr_t ram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
qxl->id = device_id++;
-
- if (ram_size < 16 * 1024 * 1024) {
- ram_size = 16 * 1024 * 1024;
- }
- qxl->vga.vram_size = ram_size;
+ qxl_init_ramsize(qxl, 16);
memory_region_init_ram(&qxl->vga.vram, &qxl->pci.qdev, "qxl.vgavram",
qxl->vga.vram_size);
qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
--
1.7.10

View File

@ -0,0 +1,63 @@
From eff66c7db18e9a3ef0b6ce5deb9a49b61090d809 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 17 Feb 2012 15:03:24 +0100
Subject: [PATCH 411/434] qxl: add user-friendly bar size properties
Add two properties to specify bar sizes in megabytes instead of bytes,
which is alot more user-friendly.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.c | 8 ++++++++
hw/qxl.h | 4 ++++
2 files changed, 12 insertions(+)
diff --git a/hw/qxl.c b/hw/qxl.c
index df8efbc..c8839c3 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1560,11 +1560,17 @@ static DisplayChangeListener display_listener = {
static void qxl_init_ramsize(PCIQXLDevice *qxl, uint32_t ram_min_mb)
{
/* vga ram (bar 0) */
+ if (qxl->ram_size_mb != -1) {
+ qxl->vga.vram_size = qxl->ram_size_mb * 1024 * 1024;
+ }
if (qxl->vga.vram_size < ram_min_mb * 1024 * 1024) {
qxl->vga.vram_size = ram_min_mb * 1024 * 1024;
}
/* vram (surfaces, bar 1) */
+ if (qxl->vram_size_mb != -1) {
+ qxl->vram_size = qxl->vram_size_mb * 1024 * 1024;
+ }
if (qxl->vram_size < 4096) {
qxl->vram_size = 4096;
}
@@ -1863,6 +1869,8 @@ static Property qxl_properties[] = {
DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
+ DEFINE_PROP_UINT32("ram_size_mb", PCIQXLDevice, ram_size_mb, -1),
+ DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram_size_mb, -1),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/qxl.h b/hw/qxl.h
index 766aa6d..d062991 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -89,6 +89,10 @@ typedef struct PCIQXLDevice {
/* io bar */
MemoryRegion io_bar;
+
+ /* user-friendly properties (in megabytes) */
+ uint32_t ram_size_mb;
+ uint32_t vram_size_mb;
} PCIQXLDevice;
#define PANIC_ON(x) if ((x)) { \
--
1.7.10

View File

@ -0,0 +1,93 @@
From 1cae61c4d4fe994e5158d63d5f4fe9b52a7b8211 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Fri, 24 Feb 2012 23:19:25 +0200
Subject: [PATCH 412/434] qxl: fix spice+sdl no cursor regression
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
regression introduced by 075360945860ad9bdd491921954b383bf762b0e5,
v2: lock around qemu_spice_cursor_refresh_unlocked
Reported-by: Fabiano Fidêncio <fabiano@fidencio.org>
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.c | 4 ++++
ui/spice-display.c | 23 ++++++++++++++---------
ui/spice-display.h | 1 +
3 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index c8839c3..17f2576 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1548,6 +1548,10 @@ static void display_refresh(struct DisplayState *ds)
{
if (qxl0->mode == QXL_MODE_VGA) {
qemu_spice_display_refresh(&qxl0->ssd);
+ } else {
+ qemu_mutex_lock(&qxl0->ssd.lock);
+ qemu_spice_cursor_refresh_unlocked(&qxl0->ssd);
+ qemu_mutex_unlock(&qxl0->ssd.lock);
}
}
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 6c302a3..c6e61d8 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -317,16 +317,8 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
ssd->notify++;
}
-void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
+void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd)
{
- dprint(3, "%s:\n", __FUNCTION__);
- vga_hw_update();
-
- qemu_mutex_lock(&ssd->lock);
- if (ssd->update == NULL) {
- ssd->update = qemu_spice_create_update(ssd);
- ssd->notify++;
- }
if (ssd->cursor) {
ssd->ds->cursor_define(ssd->cursor);
cursor_put(ssd->cursor);
@@ -337,6 +329,19 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
ssd->mouse_x = -1;
ssd->mouse_y = -1;
}
+}
+
+void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
+{
+ dprint(3, "%s:\n", __func__);
+ vga_hw_update();
+
+ qemu_mutex_lock(&ssd->lock);
+ if (ssd->update == NULL) {
+ ssd->update = qemu_spice_create_update(ssd);
+ ssd->notify++;
+ }
+ qemu_spice_cursor_refresh_unlocked(ssd);
qemu_mutex_unlock(&ssd->lock);
if (ssd->notify) {
diff --git a/ui/spice-display.h b/ui/spice-display.h
index 5e52df9..a23bfc8 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -97,6 +97,7 @@ 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_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd);
void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
qxl_async_io async);
--
1.7.10

View File

@ -0,0 +1,29 @@
From 4888e60d646b0f8cdfe4180bacc90857d3d2a5dd Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Fri, 24 Feb 2012 23:19:26 +0200
Subject: [PATCH 413/434] sdl: remove NULL check, g_malloc0 can't fail
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
ui/sdl.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/ui/sdl.c b/ui/sdl.c
index 8cafc44..6844c83 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -167,10 +167,6 @@ static PixelFormat sdl_to_qemu_pixelformat(SDL_PixelFormat *sdl_pf)
static DisplaySurface* sdl_create_displaysurface(int width, int height)
{
DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
- if (surface == NULL) {
- fprintf(stderr, "sdl_create_displaysurface: malloc failed\n");
- exit(1);
- }
surface->width = width;
surface->height = height;
--
1.7.10

View File

@ -0,0 +1,34 @@
From 813c46edf4f3f69347353749755e040bc5fbd597 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Fri, 24 Feb 2012 23:19:27 +0200
Subject: [PATCH 414/434] qxl: drop qxl_spice_update_area_async definition
It was never used. Introduced in
5ff4e36c804157bd84af43c139f8cd3a59722db9
qxl: async io support using new spice api
But not used even then.
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.h | 6 ------
1 file changed, 6 deletions(-)
diff --git a/hw/qxl.h b/hw/qxl.h
index d062991..a615eca 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -138,9 +138,3 @@ 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
--
1.7.10

View File

@ -0,0 +1,358 @@
From e07eeb01819b40b839cc12b2eb658f48f13a5ff0 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Fri, 24 Feb 2012 23:19:28 +0200
Subject: [PATCH 415/434] qxl: require spice >= 0.8.2
drop all ifdefs on SPICE_INTERFACE_QXL_MINOR >= 1 as a result,
any check for SPICE_SERVER_VERSION that is now always satisfied,
and SPICE_INTERFACE_CORE_MINOR >= 3 tests, because
0.8.2 has SPICE_INTERFACE_QXL_MINOR == 1 and
SPICE_INTERFACE_CORE_MINOR == 3.
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
configure | 2 +-
hw/qxl.c | 40 ----------------------------------------
hw/qxl.h | 4 ----
ui/spice-core.c | 17 -----------------
ui/spice-display.c | 12 ------------
5 files changed, 1 insertion(+), 74 deletions(-)
diff --git a/configure b/configure
index a4848a4..b03172c 100755
--- a/configure
+++ b/configure
@@ -2501,7 +2501,7 @@ int main(void) { spice_server_new(); return 0; }
EOF
spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null)
spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null)
- if $pkg_config --atleast-version=0.6.0 spice-server >/dev/null 2>&1 && \
+ if $pkg_config --atleast-version=0.8.2 spice-server >/dev/null 2>&1 && \
compile_prog "$spice_cflags" "$spice_libs" ; then
spice="yes"
libs_softmmu="$libs_softmmu $spice_libs"
diff --git a/hw/qxl.c b/hw/qxl.c
index 17f2576..0be9859 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -125,9 +125,7 @@ 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) {
va_list ap;
va_start(ap, msg);
@@ -149,12 +147,8 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
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
}
}
@@ -171,24 +165,18 @@ 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);
}
}
-#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)
@@ -217,11 +205,7 @@ static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
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);
@@ -493,7 +477,6 @@ static const char *io_port_to_string(uint32_t io_port)
[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",
@@ -503,7 +486,6 @@ static const char *io_port_to_string(uint32_t io_port)
= "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];
}
@@ -738,8 +720,6 @@ static int interface_flush_resources(QXLInstance *sin)
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)
{
@@ -767,8 +747,6 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
}
-#endif
-
static const QXLInterface qxl_interface = {
.base.type = SPICE_INTERFACE_QXL,
.base.description = "qxl gpu",
@@ -788,9 +766,7 @@ 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)
@@ -1140,9 +1116,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
PCIQXLDevice *d = opaque;
uint32_t io_port = addr;
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:
@@ -1152,10 +1126,8 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
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) {
@@ -1163,17 +1135,14 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
}
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) {
@@ -1212,7 +1181,6 @@ async_common:
default:
break;
}
-#endif
switch (io_port) {
case QXL_IO_UPDATE_AREA:
@@ -1304,7 +1272,6 @@ 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) {
@@ -1325,7 +1292,6 @@ async_common:
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);
@@ -1336,16 +1302,12 @@ async_common:
}
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 uint64_t ioport_read(void *opaque, target_phys_addr_t addr,
@@ -1607,9 +1569,7 @@ static int qxl_init_common(PCIQXLDevice *qxl)
case 2: /* spice 0.6 -- qxl-2 */
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;
diff --git a/hw/qxl.h b/hw/qxl.h
index a615eca..9288e46 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -108,11 +108,7 @@ 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);
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 27216e9..2c815f1 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -139,8 +139,6 @@ static void watch_remove(SpiceWatch *watch)
g_free(watch);
}
-#if SPICE_INTERFACE_CORE_MINOR >= 3
-
typedef struct ChannelList ChannelList;
struct ChannelList {
SpiceChannelEventInfo *info;
@@ -257,15 +255,6 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
}
}
-#else /* SPICE_INTERFACE_CORE_MINOR >= 3 */
-
-static QList *channel_list_get(void)
-{
- return NULL;
-}
-
-#endif /* SPICE_INTERFACE_CORE_MINOR >= 3 */
-
static SpiceCoreInterface core_interface = {
.base.type = SPICE_INTERFACE_CORE,
.base.description = "qemu core services",
@@ -281,9 +270,7 @@ static SpiceCoreInterface core_interface = {
.watch_update_mask = watch_update_mask,
.watch_remove = watch_remove,
-#if SPICE_INTERFACE_CORE_MINOR >= 3
.channel_event = channel_event,
-#endif
};
#ifdef SPICE_INTERFACE_MIGRATION
@@ -490,7 +477,6 @@ static void migration_state_notifier(Notifier *notifier, void *data)
spice_server_migrate_start(spice_server);
#endif
} else if (migration_has_finished(s)) {
-#if SPICE_SERVER_VERSION >= 0x000701 /* 0.7.1 */
#ifndef SPICE_INTERFACE_MIGRATION
spice_server_migrate_switch(spice_server);
#else
@@ -498,7 +484,6 @@ static void migration_state_notifier(Notifier *notifier, void *data)
} else if (migration_has_failed(s)) {
spice_server_migrate_end(spice_server, false);
#endif
-#endif
}
}
@@ -659,11 +644,9 @@ void qemu_spice_init(void)
spice_server_set_noauth(spice_server);
}
-#if SPICE_SERVER_VERSION >= 0x000801
if (qemu_opt_get_bool(opts, "disable-copy-paste", 0)) {
spice_server_set_agent_copypaste(spice_server, false);
}
-#endif
compression = SPICE_IMAGE_COMPRESS_AUTO_GLZ;
str = qemu_opt_get(opts, "image-compression");
diff --git a/ui/spice-display.c b/ui/spice-display.c
index c6e61d8..ad76bae 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -64,11 +64,7 @@ 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);
}
@@ -84,11 +80,7 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
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);
}
@@ -99,11 +91,7 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
uint32_t id, qxl_async_io async)
{
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);
}
--
1.7.10

View File

@ -0,0 +1,145 @@
From f9344933bcc1425cf1e8142dc2f8321522dc00af Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Fri, 24 Feb 2012 23:19:29 +0200
Subject: [PATCH 416/434] qxl: remove flipped
Tested on linux and windows guests. For negative stride, qxl_flip copies
directly to vga->ds->surface->data, for positive it's reallocated to
share qxl->guest_primary.data
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl-render.c | 66 +++++++++++++++++++++++++------------------------------
hw/qxl.h | 2 +-
2 files changed, 31 insertions(+), 37 deletions(-)
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index a7891b2..5811d74 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -23,10 +23,21 @@
static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
{
- uint8_t *src = qxl->guest_primary.data;
- uint8_t *dst = qxl->guest_primary.flipped;
+ uint8_t *src;
+ uint8_t *dst = qxl->vga.ds->surface->data;
int len, i;
+ if (qxl->guest_primary.qxl_stride > 0) {
+ return;
+ }
+ if (!qxl->guest_primary.data) {
+ dprint(qxl, 1, "%s: initializing guest_primary.data\n", __func__);
+ qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
+ }
+ dprint(qxl, 1, "%s: stride %d, [%d, %d, %d, %d]\n", __func__,
+ qxl->guest_primary.qxl_stride,
+ rect->left, rect->right, rect->top, rect->bottom);
+ src = qxl->guest_primary.data;
src += (qxl->guest_primary.surface.height - rect->top - 1) *
qxl->guest_primary.abs_stride;
dst += rect->top * qxl->guest_primary.abs_stride;
@@ -75,52 +86,38 @@ void qxl_render_update(PCIQXLDevice *qxl)
{
VGACommonState *vga = &qxl->vga;
QXLRect dirty[32], update;
- void *ptr;
int i, redraw = 0;
-
- if (!is_buffer_shared(vga->ds->surface)) {
- dprint(qxl, 1, "%s: restoring shared displaysurface\n", __func__);
- qxl->guest_primary.resized++;
- qxl->guest_primary.commands++;
- redraw = 1;
- }
+ DisplaySurface *surface = vga->ds->surface;
if (qxl->guest_primary.resized) {
qxl->guest_primary.resized = 0;
- if (qxl->guest_primary.flipped) {
- g_free(qxl->guest_primary.flipped);
- qxl->guest_primary.flipped = NULL;
- }
- qemu_free_displaysurface(vga->ds);
-
qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
- if (qxl->guest_primary.qxl_stride < 0) {
- /* spice surface is upside down -> need extra buffer to flip */
- qxl->guest_primary.flipped =
- g_malloc(qxl->guest_primary.surface.width *
- qxl->guest_primary.abs_stride);
- ptr = qxl->guest_primary.flipped;
- } else {
- ptr = qxl->guest_primary.data;
- }
- dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d, flip %s\n",
+ dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d\n",
__FUNCTION__,
qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height,
qxl->guest_primary.qxl_stride,
qxl->guest_primary.bytes_pp,
- qxl->guest_primary.bits_pp,
- qxl->guest_primary.flipped ? "yes" : "no");
- vga->ds->surface =
+ qxl->guest_primary.bits_pp);
+ }
+ if (surface->width != qxl->guest_primary.surface.width ||
+ surface->height != qxl->guest_primary.surface.height) {
+ dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
+ __func__);
+ if (qxl->guest_primary.qxl_stride > 0) {
+ qemu_free_displaysurface(vga->ds);
qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height,
qxl->guest_primary.bits_pp,
qxl->guest_primary.abs_stride,
- ptr);
- dpy_resize(vga->ds);
+ qxl->guest_primary.data);
+ } else {
+ qemu_resize_displaysurface(vga->ds,
+ qxl->guest_primary.surface.width,
+ qxl->guest_primary.surface.height);
+ }
}
-
update.left = 0;
update.right = qxl->guest_primary.surface.width;
update.top = 0;
@@ -136,14 +133,11 @@ void qxl_render_update(PCIQXLDevice *qxl)
memset(dirty, 0, sizeof(dirty));
dirty[0] = update;
}
-
for (i = 0; i < ARRAY_SIZE(dirty); i++) {
if (qemu_spice_rect_is_empty(dirty+i)) {
break;
}
- if (qxl->guest_primary.flipped) {
- qxl_flip(qxl, dirty+i);
- }
+ qxl_flip(qxl, dirty+i);
dpy_update(vga->ds,
dirty[i].left, dirty[i].top,
dirty[i].right - dirty[i].left,
diff --git a/hw/qxl.h b/hw/qxl.h
index 9288e46..53a3ace 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -52,7 +52,7 @@ typedef struct PCIQXLDevice {
uint32_t abs_stride;
uint32_t bits_pp;
uint32_t bytes_pp;
- uint8_t *data, *flipped;
+ uint8_t *data;
} guest_primary;
struct surfaces {
--
1.7.10

View File

@ -0,0 +1,264 @@
From bbe362cd6a386d98a94ac791f1263671bd79b754 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Fri, 24 Feb 2012 23:19:30 +0200
Subject: [PATCH 417/434] qxl: introduce QXLCookie
Will be used in the next patch.
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl-render.c | 2 +-
hw/qxl.c | 61 ++++++++++++++++++++++++++++++++++++++++------------
hw/qxl.h | 2 +-
ui/spice-display.c | 22 ++++++++++++++++---
ui/spice-display.h | 14 ++++++++++++
5 files changed, 82 insertions(+), 19 deletions(-)
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 5811d74..4c22166 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -127,7 +127,7 @@ void qxl_render_update(PCIQXLDevice *qxl)
if (runstate_is_running() && qxl->guest_primary.commands) {
qxl->guest_primary.commands = 0;
qxl_spice_update_area(qxl, 0, &update,
- dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
+ dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC, NULL);
}
if (redraw) {
memset(dirty, 0, sizeof(dirty));
diff --git a/hw/qxl.c b/hw/qxl.c
index 0be9859..e6e65d9 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -141,14 +141,15 @@ 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_async_io async)
+ qxl_async_io async, struct QXLCookie *cookie)
{
if (async == QXL_SYNC) {
qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area,
dirty_rects, num_dirty_rects, clear_dirty_region);
} else {
+ assert(cookie != NULL);
spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area,
- clear_dirty_region, 0);
+ clear_dirty_region, (uint64_t)cookie);
}
}
@@ -164,9 +165,13 @@ static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl,
static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
qxl_async_io async)
{
+ QXLCookie *cookie;
+
if (async) {
- spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id,
- (uint64_t)id);
+ cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_DESTROY_SURFACE_ASYNC);
+ cookie->u.surface_id = id;
+ spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uint64_t)cookie);
} else {
qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
qxl_spice_destroy_surface_wait_complete(qxl, id);
@@ -175,7 +180,9 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
{
- spice_qxl_flush_surfaces_async(&qxl->ssd.qxl, 0);
+ spice_qxl_flush_surfaces_async(&qxl->ssd.qxl,
+ (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_FLUSH_SURFACES_ASYNC));
}
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
@@ -205,7 +212,9 @@ static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
{
if (async) {
- spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl, 0);
+ spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl,
+ (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_DESTROY_ALL_SURFACES_ASYNC));
} else {
qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
qxl_spice_destroy_surfaces_complete(qxl);
@@ -721,9 +730,8 @@ static int interface_flush_resources(QXLInstance *sin)
static void qxl_create_guest_primary_complete(PCIQXLDevice *d);
/* called from spice server thread context only */
-static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
+static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
{
- PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
uint32_t current_async;
qemu_mutex_lock(&qxl->async_lock);
@@ -731,8 +739,16 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
qxl->current_async = QXL_UNDEFINED_IO;
qemu_mutex_unlock(&qxl->async_lock);
- dprint(qxl, 2, "async_complete: %d (%" PRId64 ") done\n",
- current_async, cookie);
+ dprint(qxl, 2, "async_complete: %d (%p) done\n", current_async, cookie);
+ if (!cookie) {
+ fprintf(stderr, "qxl: %s: error, cookie is NULL\n", __func__);
+ return;
+ }
+ if (cookie && current_async != cookie->io) {
+ fprintf(stderr,
+ "qxl: %s: error: current_async = %d != %ld = cookie->io\n",
+ __func__, current_async, cookie->io);
+ }
switch (current_async) {
case QXL_IO_CREATE_PRIMARY_ASYNC:
qxl_create_guest_primary_complete(qxl);
@@ -741,12 +757,29 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
qxl_spice_destroy_surfaces_complete(qxl);
break;
case QXL_IO_DESTROY_SURFACE_ASYNC:
- qxl_spice_destroy_surface_wait_complete(qxl, (uint32_t)cookie);
+ qxl_spice_destroy_surface_wait_complete(qxl, cookie->u.surface_id);
break;
}
qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
}
+/* called from spice server thread context only */
+static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
+{
+ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+ QXLCookie *cookie = (QXLCookie *)cookie_token;
+
+ switch (cookie->type) {
+ case QXL_COOKIE_TYPE_IO:
+ interface_async_complete_io(qxl, cookie);
+ break;
+ default:
+ fprintf(stderr, "qxl: %s: unexpected cookie type %d\n",
+ __func__, cookie->type);
+ }
+ g_free(cookie);
+}
+
static const QXLInterface qxl_interface = {
.base.type = SPICE_INTERFACE_QXL,
.base.description = "qxl gpu",
@@ -1057,9 +1090,7 @@ static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
if (d->mode == QXL_MODE_UNDEFINED) {
return 0;
}
-
dprint(d, 1, "%s\n", __FUNCTION__);
-
d->mode = QXL_MODE_UNDEFINED;
qemu_spice_destroy_primary_surface(&d->ssd, 0, async);
qxl_spice_reset_cursor(d);
@@ -1187,7 +1218,9 @@ async_common:
{
QXLRect update = d->ram->update_area;
qxl_spice_update_area(d, d->ram->update_surface,
- &update, NULL, 0, 0, async);
+ &update, NULL, 0, 0, async,
+ qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_UPDATE_AREA_ASYNC));
break;
}
case QXL_IO_NOTIFY_CMD:
diff --git a/hw/qxl.h b/hw/qxl.h
index 53a3ace..1443925 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -118,7 +118,7 @@ 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_async_io async);
+ qxl_async_io async, QXLCookie *cookie);
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
uint32_t count);
void qxl_spice_oom(PCIQXLDevice *qxl);
diff --git a/ui/spice-display.c b/ui/spice-display.c
index ad76bae..ab266ae 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -60,11 +60,23 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
dest->right = MAX(dest->right, r->right);
}
+QXLCookie *qxl_cookie_new(int type, uint64_t io)
+{
+ QXLCookie *cookie;
+
+ cookie = g_malloc0(sizeof(*cookie));
+ cookie->type = type;
+ cookie->io = io;
+ return cookie;
+}
+
void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
qxl_async_io async)
{
if (async != QXL_SYNC) {
- spice_qxl_add_memslot_async(&ssd->qxl, memslot, 0);
+ spice_qxl_add_memslot_async(&ssd->qxl, memslot,
+ (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_MEMSLOT_ADD_ASYNC));
} else {
ssd->worker->add_memslot(ssd->worker, memslot);
}
@@ -80,7 +92,9 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
qxl_async_io async)
{
if (async != QXL_SYNC) {
- spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface, 0);
+ spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface,
+ (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_CREATE_PRIMARY_ASYNC));
} else {
ssd->worker->create_primary_surface(ssd->worker, id, surface);
}
@@ -91,7 +105,9 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
uint32_t id, qxl_async_io async)
{
if (async != QXL_SYNC) {
- spice_qxl_destroy_primary_surface_async(&ssd->qxl, id, 0);
+ spice_qxl_destroy_primary_surface_async(&ssd->qxl, id,
+ (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_DESTROY_PRIMARY_ASYNC));
} else {
ssd->worker->destroy_primary_surface(ssd->worker, id);
}
diff --git a/ui/spice-display.h b/ui/spice-display.h
index a23bfc8..8a010cb 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -48,6 +48,20 @@ typedef enum qxl_async_io {
QXL_ASYNC,
} qxl_async_io;
+enum {
+ QXL_COOKIE_TYPE_IO,
+};
+
+typedef struct QXLCookie {
+ int type;
+ uint64_t io;
+ union {
+ uint32_t surface_id;
+ } u;
+} QXLCookie;
+
+QXLCookie *qxl_cookie_new(int type, uint64_t io);
+
typedef struct SimpleSpiceDisplay SimpleSpiceDisplay;
typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
--
1.7.10

View File

@ -0,0 +1,360 @@
From c26805e29312fee136008a57c70a2f5f140ba706 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Fri, 24 Feb 2012 23:19:31 +0200
Subject: [PATCH 418/434] qxl: make qxl_render_update async
RHBZ# 747011
Removes the last user of QXL_SYNC when using update drivers that use the
_ASYNC io ports.
The last user is qxl_render_update, it is called both by qxl_hw_update
which is the vga_hw_update_ptr passed to graphic_console_init, and by
qxl_hw_screen_dump.
At the same time the QXLRect area being passed to the red_worker thread
is passed as a copy, as part of the QXLCookie.
The implementation uses interface_update_area_complete with a bh to make
sure dpy_update and qxl_flip are called from the io thread, otherwise
the vga->ds->surface.data can change under our feet.
With this patch sdl+spice works fine. But spice by itself doesn't
produce the expected screendumps unless repeated a few times, due to
ppm_save being called before update_area (rendering done in spice server
thread) having a chance to complete. Fixed by next patch, but see commit
message for problem introduced by it.
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl-render.c | 96 +++++++++++++++++++++++++++++++++++++---------------
hw/qxl.c | 69 ++++++++++++++++++++++++++++++++++---
hw/qxl.h | 10 ++++++
ui/spice-display.h | 6 ++++
4 files changed, 150 insertions(+), 31 deletions(-)
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 4c22166..4857838 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -82,17 +82,25 @@ void qxl_render_resize(PCIQXLDevice *qxl)
}
}
-void qxl_render_update(PCIQXLDevice *qxl)
+static void qxl_set_rect_to_surface(PCIQXLDevice *qxl, QXLRect *area)
+{
+ area->left = 0;
+ area->right = qxl->guest_primary.surface.width;
+ area->top = 0;
+ area->bottom = qxl->guest_primary.surface.height;
+}
+
+static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
{
VGACommonState *vga = &qxl->vga;
- QXLRect dirty[32], update;
- int i, redraw = 0;
+ int i;
DisplaySurface *surface = vga->ds->surface;
if (qxl->guest_primary.resized) {
qxl->guest_primary.resized = 0;
-
qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
+ qxl_set_rect_to_surface(qxl, &qxl->dirty[0]);
+ qxl->num_dirty_rects = 1;
dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d\n",
__FUNCTION__,
qxl->guest_primary.surface.width,
@@ -103,9 +111,9 @@ void qxl_render_update(PCIQXLDevice *qxl)
}
if (surface->width != qxl->guest_primary.surface.width ||
surface->height != qxl->guest_primary.surface.height) {
- dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
- __func__);
if (qxl->guest_primary.qxl_stride > 0) {
+ dprint(qxl, 1, "%s: using guest_primary for displaysurface\n",
+ __func__);
qemu_free_displaysurface(vga->ds);
qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height,
@@ -113,36 +121,70 @@ void qxl_render_update(PCIQXLDevice *qxl)
qxl->guest_primary.abs_stride,
qxl->guest_primary.data);
} else {
+ dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
+ __func__);
qemu_resize_displaysurface(vga->ds,
qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height);
}
}
- update.left = 0;
- update.right = qxl->guest_primary.surface.width;
- update.top = 0;
- update.bottom = qxl->guest_primary.surface.height;
-
- memset(dirty, 0, sizeof(dirty));
- if (runstate_is_running() && qxl->guest_primary.commands) {
- qxl->guest_primary.commands = 0;
- qxl_spice_update_area(qxl, 0, &update,
- dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC, NULL);
- }
- if (redraw) {
- memset(dirty, 0, sizeof(dirty));
- dirty[0] = update;
- }
- for (i = 0; i < ARRAY_SIZE(dirty); i++) {
- if (qemu_spice_rect_is_empty(dirty+i)) {
+ for (i = 0; i < qxl->num_dirty_rects; i++) {
+ if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
break;
}
- qxl_flip(qxl, dirty+i);
+ qxl_flip(qxl, qxl->dirty+i);
dpy_update(vga->ds,
- dirty[i].left, dirty[i].top,
- dirty[i].right - dirty[i].left,
- dirty[i].bottom - dirty[i].top);
+ qxl->dirty[i].left, qxl->dirty[i].top,
+ qxl->dirty[i].right - qxl->dirty[i].left,
+ qxl->dirty[i].bottom - qxl->dirty[i].top);
+ }
+ qxl->num_dirty_rects = 0;
+}
+
+/*
+ * use ssd.lock to protect render_update_cookie_num.
+ * qxl_render_update is called by io thread or vcpu thread, and the completion
+ * callbacks are called by spice_server thread, defering to bh called from the
+ * io thread.
+ */
+void qxl_render_update(PCIQXLDevice *qxl)
+{
+ QXLCookie *cookie;
+
+ qemu_mutex_lock(&qxl->ssd.lock);
+
+ if (!runstate_is_running() || !qxl->guest_primary.commands) {
+ qxl_render_update_area_unlocked(qxl);
+ qemu_mutex_unlock(&qxl->ssd.lock);
+ return;
}
+
+ qxl->guest_primary.commands = 0;
+ qxl->render_update_cookie_num++;
+ qemu_mutex_unlock(&qxl->ssd.lock);
+ cookie = qxl_cookie_new(QXL_COOKIE_TYPE_RENDER_UPDATE_AREA,
+ 0);
+ qxl_set_rect_to_surface(qxl, &cookie->u.render.area);
+ qxl_spice_update_area(qxl, 0, &cookie->u.render.area, NULL,
+ 0, 1 /* clear_dirty_region */, QXL_ASYNC, cookie);
+}
+
+void qxl_render_update_area_bh(void *opaque)
+{
+ PCIQXLDevice *qxl = opaque;
+
+ qemu_mutex_lock(&qxl->ssd.lock);
+ qxl_render_update_area_unlocked(qxl);
+ qemu_mutex_unlock(&qxl->ssd.lock);
+}
+
+void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie)
+{
+ qemu_mutex_lock(&qxl->ssd.lock);
+ qemu_bh_schedule(qxl->update_area_bh);
+ qxl->render_update_cookie_num--;
+ qemu_mutex_unlock(&qxl->ssd.lock);
+ g_free(cookie);
}
static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor)
diff --git a/hw/qxl.c b/hw/qxl.c
index e6e65d9..73be115 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -750,6 +750,11 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
__func__, current_async, cookie->io);
}
switch (current_async) {
+ case QXL_IO_MEMSLOT_ADD_ASYNC:
+ case QXL_IO_DESTROY_PRIMARY_ASYNC:
+ case QXL_IO_UPDATE_AREA_ASYNC:
+ case QXL_IO_FLUSH_SURFACES_ASYNC:
+ break;
case QXL_IO_CREATE_PRIMARY_ASYNC:
qxl_create_guest_primary_complete(qxl);
break;
@@ -759,11 +764,54 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
case QXL_IO_DESTROY_SURFACE_ASYNC:
qxl_spice_destroy_surface_wait_complete(qxl, cookie->u.surface_id);
break;
+ default:
+ fprintf(stderr, "qxl: %s: unexpected current_async %d\n", __func__,
+ current_async);
}
qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
}
/* called from spice server thread context only */
+static void interface_update_area_complete(QXLInstance *sin,
+ uint32_t surface_id,
+ QXLRect *dirty, uint32_t num_updated_rects)
+{
+ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+ int i;
+ int qxl_i;
+
+ qemu_mutex_lock(&qxl->ssd.lock);
+ if (surface_id != 0 || !qxl->render_update_cookie_num) {
+ qemu_mutex_unlock(&qxl->ssd.lock);
+ return;
+ }
+ if (qxl->num_dirty_rects + num_updated_rects > QXL_NUM_DIRTY_RECTS) {
+ /*
+ * overflow - treat this as a full update. Not expected to be common.
+ */
+ dprint(qxl, 1, "%s: overflow of dirty rects\n", __func__);
+ qxl->guest_primary.resized = 1;
+ }
+ if (qxl->guest_primary.resized) {
+ /*
+ * Don't bother copying or scheduling the bh since we will flip
+ * the whole area anyway on completion of the update_area async call
+ */
+ qemu_mutex_unlock(&qxl->ssd.lock);
+ return;
+ }
+ qxl_i = qxl->num_dirty_rects;
+ for (i = 0; i < num_updated_rects; i++) {
+ qxl->dirty[qxl_i++] = dirty[i];
+ }
+ qxl->num_dirty_rects += num_updated_rects;
+ dprint(qxl, 1, "%s: scheduling update_area_bh, #dirty %d\n",
+ __func__, qxl->num_dirty_rects);
+ qemu_bh_schedule(qxl->update_area_bh);
+ qemu_mutex_unlock(&qxl->ssd.lock);
+}
+
+/* called from spice server thread context only */
static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
@@ -772,12 +820,16 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
switch (cookie->type) {
case QXL_COOKIE_TYPE_IO:
interface_async_complete_io(qxl, cookie);
+ g_free(cookie);
+ break;
+ case QXL_COOKIE_TYPE_RENDER_UPDATE_AREA:
+ qxl_render_update_area_done(qxl, cookie);
break;
default:
fprintf(stderr, "qxl: %s: unexpected cookie type %d\n",
__func__, cookie->type);
+ g_free(cookie);
}
- g_free(cookie);
}
static const QXLInterface qxl_interface = {
@@ -800,6 +852,7 @@ static const QXLInterface qxl_interface = {
.notify_update = interface_notify_update,
.flush_resources = interface_flush_resources,
.async_complete = interface_async_complete,
+ .update_area_complete = interface_update_area_complete,
};
static void qxl_enter_vga_mode(PCIQXLDevice *d)
@@ -1216,11 +1269,17 @@ async_common:
switch (io_port) {
case QXL_IO_UPDATE_AREA:
{
+ QXLCookie *cookie = NULL;
QXLRect update = d->ram->update_area;
+
+ if (async == QXL_ASYNC) {
+ cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_UPDATE_AREA_ASYNC);
+ cookie->u.area = update;
+ }
qxl_spice_update_area(d, d->ram->update_surface,
- &update, NULL, 0, 0, async,
- qxl_cookie_new(QXL_COOKIE_TYPE_IO,
- QXL_IO_UPDATE_AREA_ASYNC));
+ cookie ? &cookie->u.area : &update,
+ NULL, 0, 0, async, cookie);
break;
}
case QXL_IO_NOTIFY_CMD:
@@ -1652,6 +1711,8 @@ static int qxl_init_common(PCIQXLDevice *qxl)
init_pipe_signaling(qxl);
qxl_reset_state(qxl);
+ qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl);
+
return 0;
}
diff --git a/hw/qxl.h b/hw/qxl.h
index 1443925..86e415b 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -18,6 +18,8 @@ enum qxl_mode {
#define QXL_UNDEFINED_IO UINT32_MAX
+#define QXL_NUM_DIRTY_RECTS 64
+
typedef struct PCIQXLDevice {
PCIDevice pci;
SimpleSpiceDisplay ssd;
@@ -93,6 +95,12 @@ typedef struct PCIQXLDevice {
/* user-friendly properties (in megabytes) */
uint32_t ram_size_mb;
uint32_t vram_size_mb;
+
+ /* qxl_render_update state */
+ int render_update_cookie_num;
+ int num_dirty_rects;
+ QXLRect dirty[QXL_NUM_DIRTY_RECTS];
+ QEMUBH *update_area_bh;
} PCIQXLDevice;
#define PANIC_ON(x) if ((x)) { \
@@ -134,3 +142,5 @@ 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);
+void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie);
+void qxl_render_update_area_bh(void *opaque);
diff --git a/ui/spice-display.h b/ui/spice-display.h
index 8a010cb..12e50b6 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -50,6 +50,7 @@ typedef enum qxl_async_io {
enum {
QXL_COOKIE_TYPE_IO,
+ QXL_COOKIE_TYPE_RENDER_UPDATE_AREA,
};
typedef struct QXLCookie {
@@ -57,6 +58,11 @@ typedef struct QXLCookie {
uint64_t io;
union {
uint32_t surface_id;
+ QXLRect area;
+ struct {
+ QXLRect area;
+ int redraw;
+ } render;
} u;
} QXLCookie;
--
1.7.10

View File

@ -0,0 +1,102 @@
From 2b973a5ea22635211cbde2e559cc6e6355ca8205 Mon Sep 17 00:00:00 2001
From: Christophe Fergeau <cfergeau@redhat.com>
Date: Fri, 24 Feb 2012 18:13:12 +0100
Subject: [PATCH 419/434] spice: use error_report to report errors
Error message reporting during spice startup wasn't consistent, it was done
with fprintf(stderr, "") but sometimes the message didn't have a trailing
\n. Using error_report make the intent of the message clearer and deal
with the final \n for us.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
ui/spice-core.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 2c815f1..8503f03 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -227,8 +227,8 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
add_addr_info(server, (struct sockaddr *)&info->laddr_ext,
info->llen_ext);
} else {
- fprintf(stderr, "spice: %s, extended address is expected\n",
- __func__);
+ error_report("spice: %s, extended address is expected",
+ __func__);
#endif
add_addr_info(client, &info->paddr, info->plen);
add_addr_info(server, &info->laddr, info->llen);
@@ -333,7 +333,7 @@ static int parse_name(const char *string, const char *optname,
if (value != -1) {
return value;
}
- fprintf(stderr, "spice: invalid %s: %s\n", optname, string);
+ error_report("spice: invalid %s: %s", optname, string);
exit(1);
}
@@ -525,7 +525,7 @@ static int add_channel(const char *name, const char *value, void *opaque)
rc = spice_server_set_channel_security(spice_server, value, security);
}
if (rc != 0) {
- fprintf(stderr, "spice: failed to set channel security for %s\n", value);
+ error_report("spice: failed to set channel security for %s", value);
exit(1);
}
return 0;
@@ -553,15 +553,15 @@ void qemu_spice_init(void)
port = qemu_opt_get_number(opts, "port", 0);
tls_port = qemu_opt_get_number(opts, "tls-port", 0);
if (!port && !tls_port) {
- fprintf(stderr, "neither port nor tls-port specified for spice.");
+ error_report("neither port nor tls-port specified for spice");
exit(1);
}
if (port < 0 || port > 65535) {
- fprintf(stderr, "spice port is out of range");
+ error_report("spice port is out of range");
exit(1);
}
if (tls_port < 0 || tls_port > 65535) {
- fprintf(stderr, "spice tls-port is out of range");
+ error_report("spice tls-port is out of range");
exit(1);
}
password = qemu_opt_get(opts, "password");
@@ -631,11 +631,11 @@ void qemu_spice_init(void)
#if SPICE_SERVER_VERSION >= 0x000900 /* 0.9.0 */
if (spice_server_set_sasl_appname(spice_server, "qemu") == -1 ||
spice_server_set_sasl(spice_server, 1) == -1) {
- fprintf(stderr, "spice: failed to enable sasl\n");
+ error_report("spice: failed to enable sasl");
exit(1);
}
#else
- fprintf(stderr, "spice: sasl is not available (spice >= 0.9 required)\n");
+ error_report("spice: sasl is not available (spice >= 0.9 required)");
exit(1);
#endif
}
@@ -683,7 +683,7 @@ void qemu_spice_init(void)
qemu_opt_foreach(opts, add_channel, NULL, 0);
if (0 != spice_server_init(spice_server, &core_interface)) {
- fprintf(stderr, "failed to initialize spice server");
+ error_report("failed to initialize spice server");
exit(1);
};
using_spice = 1;
@@ -708,7 +708,7 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin)
{
if (!spice_server) {
if (QTAILQ_FIRST(&qemu_spice_opts.head) != NULL) {
- fprintf(stderr, "Oops: spice configured but not active\n");
+ error_report("Oops: spice configured but not active");
exit(1);
}
/*
--
1.7.10

View File

@ -0,0 +1,44 @@
From d01f59d652b8ac906ecd129afa338f56b2aaef90 Mon Sep 17 00:00:00 2001
From: Christophe Fergeau <cfergeau@redhat.com>
Date: Fri, 24 Feb 2012 18:28:32 +0100
Subject: [PATCH 420/434] Error out when tls-channel option is used without
TLS
It's currently possible to setup spice channels using TLS when
no TLS port has been specified (ie TLS is disabled). This cannot
work, so better to error out in such a situation.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
ui/spice-core.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 8503f03..98356b0 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -511,6 +511,12 @@ static int add_channel(const char *name, const char *value, void *opaque)
int rc;
if (strcmp(name, "tls-channel") == 0) {
+ int *tls_port = opaque;
+ if (!*tls_port) {
+ error_report("spice: tried to setup tls-channel"
+ " without specifying a TLS port");
+ exit(1);
+ }
security = SPICE_CHANNEL_SECURITY_SSL;
}
if (strcmp(name, "plaintext-channel") == 0) {
@@ -680,7 +686,7 @@ void qemu_spice_init(void)
spice_server_set_playback_compression
(spice_server, qemu_opt_get_bool(opts, "playback-compression", 1));
- qemu_opt_foreach(opts, add_channel, NULL, 0);
+ qemu_opt_foreach(opts, add_channel, &tls_port, 0);
if (0 != spice_server_init(spice_server, &core_interface)) {
error_report("failed to initialize spice server");
--
1.7.10

View File

@ -0,0 +1,77 @@
From 7027fa0d3be22f48a51420a45aff13bec54fef1e Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Mon, 27 Feb 2012 11:05:09 +0100
Subject: [PATCH 421/434] qxl: properly handle upright and non-shared surfaces
Although qxl creates a shared displaysurface when the qxl surface is
upright and doesn't need to be flipped there is no guarantee that the
surface doesn't become unshared for some reason. Rename qxl_flip to
qxl_blit and fix it to handle both flip and non-flip cases.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl-render.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 4857838..2e10e93 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -21,25 +21,31 @@
#include "qxl.h"
-static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
+static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
{
uint8_t *src;
uint8_t *dst = qxl->vga.ds->surface->data;
int len, i;
- if (qxl->guest_primary.qxl_stride > 0) {
+ if (is_buffer_shared(qxl->vga.ds->surface)) {
return;
}
if (!qxl->guest_primary.data) {
dprint(qxl, 1, "%s: initializing guest_primary.data\n", __func__);
qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
}
- dprint(qxl, 1, "%s: stride %d, [%d, %d, %d, %d]\n", __func__,
+ dprint(qxl, 2, "%s: stride %d, [%d, %d, %d, %d]\n", __func__,
qxl->guest_primary.qxl_stride,
rect->left, rect->right, rect->top, rect->bottom);
src = qxl->guest_primary.data;
- src += (qxl->guest_primary.surface.height - rect->top - 1) *
- qxl->guest_primary.abs_stride;
+ if (qxl->guest_primary.qxl_stride < 0) {
+ /* qxl surface is upside down, walk src scanlines
+ * in reverse order to flip it */
+ src += (qxl->guest_primary.surface.height - rect->top - 1) *
+ qxl->guest_primary.abs_stride;
+ } else {
+ src += rect->top * qxl->guest_primary.abs_stride;
+ }
dst += rect->top * qxl->guest_primary.abs_stride;
src += rect->left * qxl->guest_primary.bytes_pp;
dst += rect->left * qxl->guest_primary.bytes_pp;
@@ -48,7 +54,7 @@ static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
for (i = rect->top; i < rect->bottom; i++) {
memcpy(dst, src, len);
dst += qxl->guest_primary.abs_stride;
- src -= qxl->guest_primary.abs_stride;
+ src += qxl->guest_primary.qxl_stride;
}
}
@@ -132,7 +138,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
break;
}
- qxl_flip(qxl, qxl->dirty+i);
+ qxl_blit(qxl, qxl->dirty+i);
dpy_update(vga->ds,
qxl->dirty[i].left, qxl->dirty[i].top,
qxl->dirty[i].right - qxl->dirty[i].left,
--
1.7.10

View File

@ -0,0 +1,39 @@
From 544cfc4a2c730aca346df7215a0dd83280f864d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
Date: Mon, 5 Mar 2012 18:22:26 +0100
Subject: [PATCH 422/434] spice: set spice uuid and name
This allows a Spice client to identify a VM
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
ui/spice-core.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 98356b0..4ad0a67 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -19,6 +19,7 @@
#include <spice-experimental.h>
#include <netdb.h>
+#include "sysemu.h"
#include "qemu-common.h"
#include "qemu-spice.h"
@@ -688,6 +689,11 @@ void qemu_spice_init(void)
qemu_opt_foreach(opts, add_channel, &tls_port, 0);
+#if SPICE_SERVER_VERSION >= 0x000a02 /* 0.10.2 */
+ spice_server_set_name(spice_server, qemu_name);
+ spice_server_set_uuid(spice_server, qemu_uuid);
+#endif
+
if (0 != spice_server_init(spice_server, &core_interface)) {
error_report("failed to initialize spice server");
exit(1);
--
1.7.10

View File

@ -0,0 +1,35 @@
From 63f3e6ee49e0a88bbd7915d81962c9046205c411 Mon Sep 17 00:00:00 2001
From: Yonit Halperin <yhalperi@redhat.com>
Date: Sun, 18 Mar 2012 09:42:39 +0200
Subject: [PATCH 423/434] monitor: fix client_migrate_info error handling
Report QERR_MISSING_PARAMETER when port is missing. Otherwise
QERR_UNDEFINED_ERROR will occur.
rhbz #795652
Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
monitor.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/monitor.c b/monitor.c
index 3c23aa4..76739d7 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1046,6 +1046,11 @@ static int client_migrate_info(Monitor *mon, const QDict *qdict,
return -1;
}
+ if (port == -1 && tls_port == -1) {
+ qerror_report(QERR_MISSING_PARAMETER, "port/tls-port");
+ return -1;
+ }
+
ret = qemu_spice_migrate_info(hostname, port, tls_port, subject,
cb, opaque);
if (ret != 0) {
--
1.7.10

View File

@ -0,0 +1,49 @@
From d3e6c37f68e7e4573a47b0540f626a2add0d05e4 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Sun, 18 Mar 2012 13:46:13 +0100
Subject: [PATCH 424/434] qxl: init_pipe_signaling: exit on failure
If pipe creation fails, exit, don't log and continue. Fix indentation at
the same time.
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 73be115..9ad5807 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1453,16 +1453,17 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
static void init_pipe_signaling(PCIQXLDevice *d)
{
- if (pipe(d->pipe) < 0) {
- dprint(d, 1, "%s: pipe creation failed\n", __FUNCTION__);
- return;
- }
- fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
- fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
- fcntl(d->pipe[0], F_SETOWN, getpid());
-
- qemu_thread_get_self(&d->main);
- qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
+ if (pipe(d->pipe) < 0) {
+ fprintf(stderr, "%s:%s: qxl pipe creation failed\n",
+ __FILE__, __func__);
+ exit(1);
+ }
+ fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
+ fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
+ fcntl(d->pipe[0], F_SETOWN, getpid());
+
+ qemu_thread_get_self(&d->main);
+ qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
}
/* graphics console */
--
1.7.10

View File

@ -0,0 +1,753 @@
From 29304ce6b6863b544f1ad8535a927dfc8864354c Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Sun, 18 Mar 2012 13:46:14 +0100
Subject: [PATCH 425/434] qxl: switch qxl.c to trace-events
dprint is still used for qxl_init_common one time prints.
also switched parts of spice-display.c over, mainly all the callbacks to
spice server.
All qxl device trace events start with the qxl device id.
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Conflicts:
trace-events
---
hw/qxl.c | 141 +++++++++++++++++++++++++---------------------------
trace-events | 59 ++++++++++++++++++++++
ui/spice-display.c | 14 +++++-
3 files changed, 140 insertions(+), 74 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 9ad5807..813873a 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -23,6 +23,7 @@
#include "qemu-queue.h"
#include "monitor.h"
#include "sysemu.h"
+#include "trace.h"
#include "qxl.h"
@@ -143,6 +144,10 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
uint32_t clear_dirty_region,
qxl_async_io async, struct QXLCookie *cookie)
{
+ trace_qxl_spice_update_area(qxl->id, surface_id, area->left, area->right,
+ area->top, area->bottom);
+ trace_qxl_spice_update_area_rest(qxl->id, 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);
@@ -156,6 +161,7 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl,
uint32_t id)
{
+ trace_qxl_spice_destroy_surface_wait_complete(qxl->id, id);
qemu_mutex_lock(&qxl->track_lock);
qxl->guest_surfaces.cmds[id] = 0;
qxl->guest_surfaces.count--;
@@ -167,6 +173,7 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
{
QXLCookie *cookie;
+ trace_qxl_spice_destroy_surface_wait(qxl->id, id, async);
if (async) {
cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
QXL_IO_DESTROY_SURFACE_ASYNC);
@@ -174,12 +181,13 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uint64_t)cookie);
} else {
qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
- qxl_spice_destroy_surface_wait_complete(qxl, id);
}
}
static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
{
+ trace_qxl_spice_flush_surfaces_async(qxl->id, qxl->guest_surfaces.count,
+ qxl->num_free_res);
spice_qxl_flush_surfaces_async(&qxl->ssd.qxl,
(uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
QXL_IO_FLUSH_SURFACES_ASYNC));
@@ -188,21 +196,25 @@ static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
uint32_t count)
{
+ trace_qxl_spice_loadvm_commands(qxl->id, ext, count);
qxl->ssd.worker->loadvm_commands(qxl->ssd.worker, ext, count);
}
void qxl_spice_oom(PCIQXLDevice *qxl)
{
+ trace_qxl_spice_oom(qxl->id);
qxl->ssd.worker->oom(qxl->ssd.worker);
}
void qxl_spice_reset_memslots(PCIQXLDevice *qxl)
{
+ trace_qxl_spice_reset_memslots(qxl->id);
qxl->ssd.worker->reset_memslots(qxl->ssd.worker);
}
static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
{
+ trace_qxl_spice_destroy_surfaces_complete(qxl->id);
qemu_mutex_lock(&qxl->track_lock);
memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds));
qxl->guest_surfaces.count = 0;
@@ -211,6 +223,7 @@ static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
{
+ trace_qxl_spice_destroy_surfaces(qxl->id, async);
if (async) {
spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl,
(uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
@@ -223,11 +236,13 @@ static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
{
+ trace_qxl_spice_reset_image_cache(qxl->id);
qxl->ssd.worker->reset_image_cache(qxl->ssd.worker);
}
void qxl_spice_reset_cursor(PCIQXLDevice *qxl)
{
+ trace_qxl_spice_reset_cursor(qxl->id);
qxl->ssd.worker->reset_cursor(qxl->ssd.worker);
qemu_mutex_lock(&qxl->track_lock);
qxl->guest_cursor = 0;
@@ -412,7 +427,7 @@ static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
- dprint(qxl, 1, "%s:\n", __FUNCTION__);
+ trace_qxl_interface_attach_worker(qxl->id);
qxl->ssd.worker = qxl_worker;
}
@@ -420,7 +435,7 @@ static void interface_set_compression_level(QXLInstance *sin, int level)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
- dprint(qxl, 1, "%s: %d\n", __FUNCTION__, level);
+ trace_qxl_interface_set_compression_level(qxl->id, level);
qxl->shadow_rom.compression_level = cpu_to_le32(level);
qxl->rom->compression_level = cpu_to_le32(level);
qxl_rom_set_dirty(qxl);
@@ -430,6 +445,7 @@ static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+ trace_qxl_interface_set_mm_time(qxl->id, mm_time);
qxl->shadow_rom.mm_clock = cpu_to_le32(mm_time);
qxl->rom->mm_clock = cpu_to_le32(mm_time);
qxl_rom_set_dirty(qxl);
@@ -439,7 +455,7 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
- dprint(qxl, 1, "%s:\n", __FUNCTION__);
+ trace_qxl_interface_get_init_info(qxl->id);
info->memslot_gen_bits = MEMSLOT_GENERATION_BITS;
info->memslot_id_bits = MEMSLOT_SLOT_BITS;
info->num_memslots = NUM_MEMSLOTS;
@@ -508,9 +524,10 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
QXLCommand *cmd;
int notify, ret;
+ trace_qxl_ring_command_check(qxl->id, qxl_mode_to_string(qxl->mode));
+
switch (qxl->mode) {
case QXL_MODE_VGA:
- dprint(qxl, 2, "%s: vga\n", __FUNCTION__);
ret = false;
qemu_mutex_lock(&qxl->ssd.lock);
if (qxl->ssd.update != NULL) {
@@ -521,19 +538,18 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
}
qemu_mutex_unlock(&qxl->ssd.lock);
if (ret) {
- dprint(qxl, 2, "%s %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
+ trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
qxl_log_command(qxl, "vga", ext);
}
return ret;
case QXL_MODE_COMPAT:
case QXL_MODE_NATIVE:
case QXL_MODE_UNDEFINED:
- dprint(qxl, 4, "%s: %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
ring = &qxl->ram->cmd_ring;
if (SPICE_RING_IS_EMPTY(ring)) {
return false;
}
- dprint(qxl, 2, "%s: %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
+ trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
SPICE_RING_CONS_ITEM(ring, cmd);
ext->cmd = *cmd;
ext->group_id = MEMSLOT_GROUP_GUEST;
@@ -558,6 +574,7 @@ static int interface_req_cmd_notification(QXLInstance *sin)
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
int wait = 1;
+ trace_qxl_ring_command_req_notification(qxl->id);
switch (qxl->mode) {
case QXL_MODE_COMPAT:
case QXL_MODE_NATIVE:
@@ -595,10 +612,11 @@ static inline void qxl_push_free_res(PCIQXLDevice *d, int flush)
}
SPICE_RING_PUSH(ring, notify);
- dprint(d, 2, "free: push %d items, notify %s, ring %d/%d [%d,%d]\n",
- d->num_free_res, notify ? "yes" : "no",
- ring->prod - ring->cons, ring->num_items,
- ring->prod, ring->cons);
+ trace_qxl_ring_res_push(d->id, qxl_mode_to_string(d->mode),
+ d->guest_surfaces.count, d->num_free_res,
+ d->last_release, notify ? "yes" : "no");
+ trace_qxl_ring_res_push_rest(d->id, ring->prod - ring->cons,
+ ring->num_items, ring->prod, ring->cons);
if (notify) {
qxl_send_events(d, QXL_INTERRUPT_DISPLAY);
}
@@ -645,7 +663,7 @@ static void interface_release_resource(QXLInstance *sin,
}
qxl->last_release = ext.info;
qxl->num_free_res++;
- dprint(qxl, 3, "%4d\r", qxl->num_free_res);
+ trace_qxl_ring_res_put(qxl->id, qxl->num_free_res);
qxl_push_free_res(qxl, 0);
}
@@ -657,6 +675,8 @@ static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *
QXLCommand *cmd;
int notify;
+ trace_qxl_ring_cursor_check(qxl->id, qxl_mode_to_string(qxl->mode));
+
switch (qxl->mode) {
case QXL_MODE_COMPAT:
case QXL_MODE_NATIVE:
@@ -680,6 +700,7 @@ static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *
if (qxl->id == 0) {
qxl_render_cursor(qxl, ext);
}
+ trace_qxl_ring_cursor_get(qxl->id, qxl_mode_to_string(qxl->mode));
return true;
default:
return false;
@@ -692,6 +713,7 @@ static int interface_req_cursor_notification(QXLInstance *sin)
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
int wait = 1;
+ trace_qxl_ring_cursor_req_notification(qxl->id);
switch (qxl->mode) {
case QXL_MODE_COMPAT:
case QXL_MODE_NATIVE:
@@ -719,7 +741,6 @@ static int interface_flush_resources(QXLInstance *sin)
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
int ret;
- dprint(qxl, 1, "free: guest flush (have %d)\n", qxl->num_free_res);
ret = qxl->num_free_res;
if (ret) {
qxl_push_free_res(qxl, 1);
@@ -739,7 +760,7 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
qxl->current_async = QXL_UNDEFINED_IO;
qemu_mutex_unlock(&qxl->async_lock);
- dprint(qxl, 2, "async_complete: %d (%p) done\n", current_async, cookie);
+ trace_qxl_interface_async_complete_io(qxl->id, current_async, cookie);
if (!cookie) {
fprintf(stderr, "qxl: %s: error, cookie is NULL\n", __func__);
return;
@@ -785,11 +806,15 @@ static void interface_update_area_complete(QXLInstance *sin,
qemu_mutex_unlock(&qxl->ssd.lock);
return;
}
+ trace_qxl_interface_update_area_complete(qxl->id, surface_id, dirty->left,
+ dirty->right, dirty->top, dirty->bottom);
+ trace_qxl_interface_update_area_complete_rest(qxl->id, num_updated_rects);
if (qxl->num_dirty_rects + num_updated_rects > QXL_NUM_DIRTY_RECTS) {
/*
* overflow - treat this as a full update. Not expected to be common.
*/
- dprint(qxl, 1, "%s: overflow of dirty rects\n", __func__);
+ trace_qxl_interface_update_area_complete_overflow(qxl->id,
+ QXL_NUM_DIRTY_RECTS);
qxl->guest_primary.resized = 1;
}
if (qxl->guest_primary.resized) {
@@ -805,8 +830,8 @@ static void interface_update_area_complete(QXLInstance *sin,
qxl->dirty[qxl_i++] = dirty[i];
}
qxl->num_dirty_rects += num_updated_rects;
- dprint(qxl, 1, "%s: scheduling update_area_bh, #dirty %d\n",
- __func__, qxl->num_dirty_rects);
+ trace_qxl_interface_update_area_complete_schedule_bh(qxl->id,
+ qxl->num_dirty_rects);
qemu_bh_schedule(qxl->update_area_bh);
qemu_mutex_unlock(&qxl->ssd.lock);
}
@@ -860,7 +885,7 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d)
if (d->mode == QXL_MODE_VGA) {
return;
}
- dprint(d, 1, "%s\n", __FUNCTION__);
+ trace_qxl_enter_vga_mode(d->id);
qemu_spice_create_host_primary(&d->ssd);
d->mode = QXL_MODE_VGA;
memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty));
@@ -871,7 +896,7 @@ static void qxl_exit_vga_mode(PCIQXLDevice *d)
if (d->mode != QXL_MODE_VGA) {
return;
}
- dprint(d, 1, "%s\n", __FUNCTION__);
+ trace_qxl_exit_vga_mode(d->id);
qxl_destroy_primary(d, QXL_SYNC);
}
@@ -908,7 +933,7 @@ static void qxl_reset_state(PCIQXLDevice *d)
static void qxl_soft_reset(PCIQXLDevice *d)
{
- dprint(d, 1, "%s:\n", __FUNCTION__);
+ trace_qxl_soft_reset(d->id);
qxl_check_state(d);
if (d->id == 0) {
@@ -920,8 +945,7 @@ static void qxl_soft_reset(PCIQXLDevice *d)
static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
{
- dprint(d, 1, "%s: start%s\n", __FUNCTION__,
- loadvm ? " (loadvm)" : "");
+ trace_qxl_hard_reset(d->id, loadvm);
qxl_spice_reset_cursor(d);
qxl_spice_reset_image_cache(d);
@@ -936,13 +960,12 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
}
qemu_spice_create_host_memslot(&d->ssd);
qxl_soft_reset(d);
-
- dprint(d, 1, "%s: done\n", __FUNCTION__);
}
static void qxl_reset_handler(DeviceState *dev)
{
PCIQXLDevice *d = DO_UPCAST(PCIQXLDevice, pci.qdev, dev);
+
qxl_hard_reset(d, 0);
}
@@ -951,8 +974,8 @@ static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
VGACommonState *vga = opaque;
PCIQXLDevice *qxl = container_of(vga, PCIQXLDevice, vga);
+ trace_qxl_io_write_vga(qxl->id, qxl_mode_to_string(qxl->mode), addr, val);
if (qxl->mode != QXL_MODE_VGA) {
- dprint(qxl, 1, "%s\n", __FUNCTION__);
qxl_destroy_primary(qxl, QXL_SYNC);
qxl_soft_reset(qxl);
}
@@ -992,9 +1015,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
guest_start = le64_to_cpu(d->guest_slots[slot_id].slot.mem_start);
guest_end = le64_to_cpu(d->guest_slots[slot_id].slot.mem_end);
- dprint(d, 1, "%s: slot %d: guest phys 0x%" PRIx64 " - 0x%" PRIx64 "\n",
- __FUNCTION__, slot_id,
- guest_start, guest_end);
+ trace_qxl_memslot_add_guest(d->id, slot_id, guest_start, guest_end);
PANIC_ON(slot_id >= NUM_MEMSLOTS);
PANIC_ON(guest_start > guest_end);
@@ -1040,10 +1061,6 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
memslot.generation = d->rom->slot_generation = 0;
qxl_rom_set_dirty(d);
- dprint(d, 1, "%s: slot %d: host virt 0x%lx - 0x%lx\n",
- __FUNCTION__, memslot.slot_id,
- memslot.virt_start, memslot.virt_end);
-
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;
@@ -1053,21 +1070,19 @@ 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);
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__);
qxl_spice_reset_memslots(d);
memset(&d->guest_slots, 0, sizeof(d->guest_slots));
}
static void qxl_reset_surfaces(PCIQXLDevice *d)
{
- dprint(d, 1, "%s:\n", __FUNCTION__);
+ trace_qxl_reset_surfaces(d->id);
d->mode = QXL_MODE_UNDEFINED;
qxl_spice_destroy_surfaces(d, QXL_SYNC);
}
@@ -1109,9 +1124,6 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
assert(qxl->mode != QXL_MODE_NATIVE);
qxl_exit_vga_mode(qxl);
- dprint(qxl, 1, "%s: %dx%d\n", __FUNCTION__,
- le32_to_cpu(sc->width), le32_to_cpu(sc->height));
-
surface.format = le32_to_cpu(sc->format);
surface.height = le32_to_cpu(sc->height);
surface.mem = le64_to_cpu(sc->mem);
@@ -1120,6 +1132,10 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
surface.width = le32_to_cpu(sc->width);
surface.type = le32_to_cpu(sc->type);
surface.flags = le32_to_cpu(sc->flags);
+ trace_qxl_create_guest_primary(qxl->id, sc->width, sc->height, sc->mem,
+ sc->format, sc->position);
+ trace_qxl_create_guest_primary_rest(qxl->id, sc->stride, sc->type,
+ sc->flags);
surface.mouse_mode = true;
surface.group_id = MEMSLOT_GROUP_GUEST;
@@ -1143,7 +1159,7 @@ static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
if (d->mode == QXL_MODE_UNDEFINED) {
return 0;
}
- dprint(d, 1, "%s\n", __FUNCTION__);
+ trace_qxl_destroy_primary(d->id);
d->mode = QXL_MODE_UNDEFINED;
qemu_spice_destroy_primary_surface(&d->ssd, 0, async);
qxl_spice_reset_cursor(d);
@@ -1170,8 +1186,8 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
.mem = devmem + d->shadow_rom.draw_area_offset,
};
- dprint(d, 1, "%s: mode %d [ %d x %d @ %d bpp devmem 0x%" PRIx64 " ]\n",
- __func__, modenr, mode->x_res, mode->y_res, mode->bits, devmem);
+ trace_qxl_set_mode(d->id, modenr, mode->x_res, mode->y_res, mode->bits,
+ devmem);
if (!loadvm) {
qxl_hard_reset(d, 0);
}
@@ -1217,8 +1233,8 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
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));
+ trace_qxl_io_unexpected_vga_mode(d->id,
+ io_port, io_port_to_string(io_port));
/* be nice to buggy guest drivers */
if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
io_port <= QXL_IO_DESTROY_ALL_SURFACES_ASYNC) {
@@ -1260,11 +1276,12 @@ async_common:
}
d->current_async = orig_io_port;
qemu_mutex_unlock(&d->async_lock);
- dprint(d, 2, "start async %d (%"PRId64")\n", io_port, val);
break;
default:
break;
}
+ trace_qxl_io_write(d->id, qxl_mode_to_string(d->mode), addr, val, size,
+ async);
switch (io_port) {
case QXL_IO_UPDATE_AREA:
@@ -1300,7 +1317,6 @@ async_common:
d->oom_running = 0;
break;
case QXL_IO_SET_MODE:
- dprint(d, 1, "QXL_SET_MODE %d\n", (int)val);
qxl_set_mode(d, val, 0);
break;
case QXL_IO_LOG:
@@ -1310,7 +1326,6 @@ async_common:
}
break;
case QXL_IO_RESET:
- dprint(d, 1, "QXL_IO_RESET\n");
qxl_hard_reset(d, 0);
break;
case QXL_IO_MEMSLOT_ADD:
@@ -1338,7 +1353,6 @@ async_common:
async);
goto cancel_async;
}
- 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, async);
break;
@@ -1348,11 +1362,9 @@ async_common:
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));
+ trace_qxl_io_destroy_primary_ignored(d->id,
+ qxl_mode_to_string(d->mode));
goto cancel_async;
}
break;
@@ -1372,16 +1384,9 @@ async_common:
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"
- " (%"PRId64") (%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;
case QXL_IO_DESTROY_ALL_SURFACES:
@@ -1407,7 +1412,7 @@ static uint64_t ioport_read(void *opaque, target_phys_addr_t addr,
{
PCIQXLDevice *d = opaque;
- dprint(d, 1, "%s: unexpected\n", __FUNCTION__);
+ trace_qxl_io_read_unexpected(d->id);
return 0xff;
}
@@ -1558,8 +1563,7 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
surface_offset -= vram_start;
surface_size = cmd->u.surface_create.height *
abs(cmd->u.surface_create.stride);
- dprint(qxl, 3, "%s: dirty surface %d, offset %d, size %d\n", __func__,
- i, (int)surface_offset, surface_size);
+ trace_qxl_surfaces_dirty(qxl->id, i, (int)surface_offset, surface_size);
qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
}
}
@@ -1759,7 +1763,7 @@ static void qxl_pre_save(void *opaque)
PCIQXLDevice* d = opaque;
uint8_t *ram_start = d->vga.vram_ptr;
- dprint(d, 1, "%s:\n", __FUNCTION__);
+ trace_qxl_pre_save(d->id);
if (d->last_release == NULL) {
d->last_release_offset = 0;
} else {
@@ -1772,10 +1776,9 @@ static int qxl_pre_load(void *opaque)
{
PCIQXLDevice* d = opaque;
- dprint(d, 1, "%s: start\n", __FUNCTION__);
+ trace_qxl_pre_load(d->id);
qxl_hard_reset(d, 1);
qxl_exit_vga_mode(d);
- dprint(d, 1, "%s: done\n", __FUNCTION__);
return 0;
}
@@ -1787,7 +1790,6 @@ static void qxl_create_memslots(PCIQXLDevice *d)
if (!d->guest_slots[i].active) {
continue;
}
- dprint(d, 1, "%s: restoring guest slot %d\n", __func__, i);
qxl_add_memslot(d, i, 0, QXL_SYNC);
}
}
@@ -1799,8 +1801,6 @@ static int qxl_post_load(void *opaque, int version)
QXLCommandExt *cmds;
int in, out, newmode;
- dprint(d, 1, "%s: start\n", __FUNCTION__);
-
assert(d->last_release_offset < d->vga.vram_size);
if (d->last_release_offset == 0) {
d->last_release = NULL;
@@ -1810,8 +1810,7 @@ static int qxl_post_load(void *opaque, int version)
d->modes = (QXLModes*)((uint8_t*)d->rom + d->rom->modes_offset);
- dprint(d, 1, "%s: restore mode (%s)\n", __FUNCTION__,
- qxl_mode_to_string(d->mode));
+ trace_qxl_post_load(d->id, qxl_mode_to_string(d->mode));
newmode = d->mode;
d->mode = QXL_MODE_UNDEFINED;
@@ -1853,8 +1852,6 @@ static int qxl_post_load(void *opaque, int version)
qxl_set_mode(d, d->shadow_rom.mode, 1);
break;
}
- dprint(d, 1, "%s: done\n", __FUNCTION__);
-
return 0;
}
diff --git a/trace-events b/trace-events
index 962caca..0bc290f 100644
--- a/trace-events
+++ b/trace-events
@@ -631,3 +631,62 @@ win_helper_no_switch_pstate(uint32_t new_pstate_regs) "change_pstate: regs new=%
win_helper_wrpil(uint32_t psrpil, uint32_t new_pil) "old=%x new=%x"
win_helper_done(uint32_t tl) "tl=%d"
win_helper_retry(uint32_t tl) "tl=%d"
+
+# hw/qxl.c
+disable qxl_interface_set_mm_time(int qid, uint32_t mm_time) "%d %d"
+disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t val) "%d %s addr=%u val=%u"
+qxl_create_guest_primary(int qid, uint32_t width, uint32_t height, uint64_t mem, uint32_t format, uint32_t position) "%d %dx%d mem=%lx %d,%d"
+qxl_create_guest_primary_rest(int qid, int32_t stride, uint32_t type, uint32_t flags) "%d %d,%d,%d"
+qxl_destroy_primary(int qid) "%d"
+qxl_enter_vga_mode(int qid) "%d"
+qxl_exit_vga_mode(int qid) "%d"
+qxl_hard_reset(int qid, int64_t loadvm) "%d loadvm=%"PRId64""
+qxl_interface_async_complete_io(int qid, uint32_t current_async, void *cookie) "%d current=%d cookie=%p"
+qxl_interface_attach_worker(int qid) "%d"
+qxl_interface_get_init_info(int qid) "%d"
+qxl_interface_set_compression_level(int qid, int64_t level) "%d %"PRId64
+qxl_interface_update_area_complete(int qid, uint32_t surface_id, uint32_t dirty_left, uint32_t dirty_right, uint32_t dirty_top, uint32_t dirty_bottom) "%d surface=%d [%d,%d,%d,%d]"
+qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) "%d #=%d"
+qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d"
+qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d"
+qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s"
+qxl_io_read_unexpected(int qid) "%d"
+qxl_io_unexpected_vga_mode(int qid, uint32_t io_port, const char *desc) "%d 0x%x (%s)"
+qxl_io_write(int qid, const char *mode, uint64_t addr, uint64_t val, unsigned size, int async) "%d %s addr=%"PRIu64 " val=%"PRIu64" size=%u async=%d"
+qxl_memslot_add_guest(int qid, uint32_t slot_id, uint64_t guest_start, uint64_t guest_end) "%d %u: guest phys 0x%"PRIx64 " - 0x%" PRIx64
+qxl_post_load(int qid, const char *mode) "%d %s"
+qxl_pre_load(int qid) "%d"
+qxl_pre_save(int qid) "%d"
+qxl_reset_surfaces(int qid) "%d"
+qxl_ring_command_check(int qid, const char *mode) "%d %s"
+qxl_ring_command_get(int qid, const char *mode) "%d %s"
+qxl_ring_command_req_notification(int qid) "%d"
+qxl_ring_cursor_check(int qid, const char *mode) "%d %s"
+qxl_ring_cursor_get(int qid, const char *mode) "%d %s"
+qxl_ring_cursor_req_notification(int qid) "%d"
+qxl_ring_res_push(int qid, const char *mode, uint32_t surface_count, uint32_t free_res, void *last_release, const char *notify) "%d %s s#=%d res#=%d last=%p notify=%s"
+qxl_ring_res_push_rest(int qid, uint32_t ring_has, uint32_t ring_size, uint32_t prod, uint32_t cons) "%d ring %d/%d [%d,%d]"
+qxl_ring_res_put(int qid, uint32_t free_res) "%d #res=%d"
+qxl_set_mode(int qid, int modenr, uint32_t x_res, uint32_t y_res, uint32_t bits, uint64_t devmem) "%d mode=%d [ x=%d y=%d @ bpp=%d devmem=0x%" PRIx64 " ]"
+qxl_soft_reset(int qid) "%d"
+qemu_spice_add_memslot(int qid, uint32_t slot_id, unsigned long virt_start, unsigned long virt_end, int async) "%d %u: host virt 0x%lx - 0x%lx async=%d"
+qemu_spice_del_memslot(int qid, uint32_t gid, uint32_t slot_id) "%d gid=%u sid=%u"
+qemu_spice_create_primary_surface(int qid, uint32_t sid, void *surface, int async) "%d sid=%u surface=%p async=%d"
+qemu_spice_destroy_primary_surface(int qid, uint32_t sid, int async) "%d sid=%u async=%d"
+qemu_spice_wakeup(uint32_t qid) "%d"
+qemu_spice_start(uint32_t qid) "%d"
+qemu_spice_stop(uint32_t qid) "%d"
+qemu_spice_create_update(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "lr %d -> %d, tb -> %d -> %d"
+qxl_spice_destroy_surfaces_complete(int qid) "%d"
+qxl_spice_destroy_surfaces(int qid, int async) "%d async=%d"
+qxl_spice_destroy_surface_wait_complete(int qid, uint32_t id) "%d sid=%d"
+qxl_spice_destroy_surface_wait(int qid, uint32_t id, int async) "%d sid=%d async=%d"
+qxl_spice_flush_surfaces_async(int qid, uint32_t surface_count, uint32_t num_free_res) "%d s#=%d, res#=%d"
+qxl_spice_loadvm_commands(int qid, void *ext, uint32_t count) "%d ext=%p count=%d"
+qxl_spice_oom(int qid) "%d"
+qxl_spice_reset_cursor(int qid) "%d"
+qxl_spice_reset_image_cache(int qid) "%d"
+qxl_spice_reset_memslots(int qid) "%d"
+qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "%d sid=%d [%d,%d,%d,%d]"
+qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d"
+qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d"
diff --git a/ui/spice-display.c b/ui/spice-display.c
index ab266ae..28d6d4a 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -22,6 +22,7 @@
#include "monitor.h"
#include "console.h"
#include "sysemu.h"
+#include "trace.h"
#include "spice-display.h"
@@ -73,6 +74,10 @@ QXLCookie *qxl_cookie_new(int type, uint64_t io)
void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
qxl_async_io async)
{
+ trace_qemu_spice_add_memslot(ssd->qxl.id, memslot->slot_id,
+ memslot->virt_start, memslot->virt_end,
+ async);
+
if (async != QXL_SYNC) {
spice_qxl_add_memslot_async(&ssd->qxl, memslot,
(uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
@@ -84,6 +89,7 @@ void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid)
{
+ trace_qemu_spice_del_memslot(ssd->qxl.id, gid, sid);
ssd->worker->del_memslot(ssd->worker, gid, sid);
}
@@ -91,6 +97,7 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
QXLDevSurfaceCreate *surface,
qxl_async_io async)
{
+ trace_qemu_spice_create_primary_surface(ssd->qxl.id, id, surface, async);
if (async != QXL_SYNC) {
spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface,
(uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
@@ -100,10 +107,10 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
}
}
-
void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
uint32_t id, qxl_async_io async)
{
+ trace_qemu_spice_destroy_primary_surface(ssd->qxl.id, id, async);
if (async != QXL_SYNC) {
spice_qxl_destroy_primary_surface_async(&ssd->qxl, id,
(uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
@@ -115,16 +122,19 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
void qemu_spice_wakeup(SimpleSpiceDisplay *ssd)
{
+ trace_qemu_spice_wakeup(ssd->qxl.id);
ssd->worker->wakeup(ssd->worker);
}
void qemu_spice_start(SimpleSpiceDisplay *ssd)
{
+ trace_qemu_spice_start(ssd->qxl.id);
ssd->worker->start(ssd->worker);
}
void qemu_spice_stop(SimpleSpiceDisplay *ssd)
{
+ trace_qemu_spice_stop(ssd->qxl.id);
ssd->worker->stop(ssd->worker);
}
@@ -142,7 +152,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
return NULL;
};
- dprint(2, "%s: lr %d -> %d, tb -> %d -> %d\n", __FUNCTION__,
+ trace_qemu_spice_create_update(
ssd->dirty.left, ssd->dirty.right,
ssd->dirty.top, ssd->dirty.bottom);
--
1.7.10

View File

@ -0,0 +1,95 @@
From 6b3e0d7afd011b8d40207fe45f6518937df1d99e Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Sun, 18 Mar 2012 13:46:15 +0100
Subject: [PATCH 426/434] qxl/qxl_render.c: add trace events
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Cherry-pick: Added missing include "trace.h"
---
hw/qxl-render.c | 14 +++++---------
trace-events | 7 +++++++
2 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 2e10e93..835dc5e 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -20,6 +20,7 @@
*/
#include "qxl.h"
+#include "trace.h"
static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
{
@@ -31,11 +32,10 @@ static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
return;
}
if (!qxl->guest_primary.data) {
- dprint(qxl, 1, "%s: initializing guest_primary.data\n", __func__);
+ trace_qxl_render_blit_guest_primary_initialized();
qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
}
- dprint(qxl, 2, "%s: stride %d, [%d, %d, %d, %d]\n", __func__,
- qxl->guest_primary.qxl_stride,
+ trace_qxl_render_blit(qxl->guest_primary.qxl_stride,
rect->left, rect->right, rect->top, rect->bottom);
src = qxl->guest_primary.data;
if (qxl->guest_primary.qxl_stride < 0) {
@@ -107,8 +107,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
qxl_set_rect_to_surface(qxl, &qxl->dirty[0]);
qxl->num_dirty_rects = 1;
- dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d\n",
- __FUNCTION__,
+ trace_qxl_render_guest_primary_resized(
qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height,
qxl->guest_primary.qxl_stride,
@@ -118,8 +117,6 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
if (surface->width != qxl->guest_primary.surface.width ||
surface->height != qxl->guest_primary.surface.height) {
if (qxl->guest_primary.qxl_stride > 0) {
- dprint(qxl, 1, "%s: using guest_primary for displaysurface\n",
- __func__);
qemu_free_displaysurface(vga->ds);
qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height,
@@ -127,8 +124,6 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->guest_primary.abs_stride,
qxl->guest_primary.data);
} else {
- dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
- __func__);
qemu_resize_displaysurface(vga->ds,
qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height);
@@ -187,6 +182,7 @@ void qxl_render_update_area_bh(void *opaque)
void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie)
{
qemu_mutex_lock(&qxl->ssd.lock);
+ trace_qxl_render_update_area_done(cookie);
qemu_bh_schedule(qxl->update_area_bh);
qxl->render_update_cookie_num--;
qemu_mutex_unlock(&qxl->ssd.lock);
diff --git a/trace-events b/trace-events
index 0bc290f..6050d92 100644
--- a/trace-events
+++ b/trace-events
@@ -690,3 +690,10 @@ qxl_spice_reset_memslots(int qid) "%d"
qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "%d sid=%d [%d,%d,%d,%d]"
qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d"
qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d"
+qxl_vga_ioport_while_not_in_vga_mode(int qid) "%d (int qid, reset to VGA mode because of VGA io)"
+
+# hw/qxl-render.c
+qxl_render_blit_guest_primary_initialized(void) ""
+qxl_render_blit(int32_t stride, int32_t left, int32_t right, int32_t top, int32_t bottom) "stride=%d [%d, %d, %d, %d]"
+qxl_render_guest_primary_resized(int32_t width, int32_t height, int32_t stride, int32_t bytes_pp, int32_t bits_pp) "%dx%d, stride %d, bpp %d, depth %d"
+qxl_render_update_area_done(void *cookie) "%p"
--
1.7.10

View File

@ -0,0 +1,80 @@
From 1ca7f74b31de28e9170e404ce2b932e311e4d2d0 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Fri, 16 Mar 2012 13:50:04 +0000
Subject: [PATCH 427/434] hw/qxl.c: Fix compilation failures on 32 bit hosts
Fix compilation failures on 32 bit hosts (cast from pointer to
integer of different size; %ld expects 'long int' not uint64_t).
Reported-by: Steve Langasek <steve.langasek@canonical.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 813873a..bcdf274 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -154,7 +154,7 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
} else {
assert(cookie != NULL);
spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area,
- clear_dirty_region, (uint64_t)cookie);
+ clear_dirty_region, (uintptr_t)cookie);
}
}
@@ -178,7 +178,7 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
QXL_IO_DESTROY_SURFACE_ASYNC);
cookie->u.surface_id = id;
- spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uint64_t)cookie);
+ spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uintptr_t)cookie);
} else {
qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
}
@@ -189,8 +189,8 @@ static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
trace_qxl_spice_flush_surfaces_async(qxl->id, qxl->guest_surfaces.count,
qxl->num_free_res);
spice_qxl_flush_surfaces_async(&qxl->ssd.qxl,
- (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
- QXL_IO_FLUSH_SURFACES_ASYNC));
+ (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_FLUSH_SURFACES_ASYNC));
}
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
@@ -226,8 +226,8 @@ static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
trace_qxl_spice_destroy_surfaces(qxl->id, async);
if (async) {
spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl,
- (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
- QXL_IO_DESTROY_ALL_SURFACES_ASYNC));
+ (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_DESTROY_ALL_SURFACES_ASYNC));
} else {
qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
qxl_spice_destroy_surfaces_complete(qxl);
@@ -767,7 +767,7 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
}
if (cookie && current_async != cookie->io) {
fprintf(stderr,
- "qxl: %s: error: current_async = %d != %ld = cookie->io\n",
+ "qxl: %s: error: current_async = %d != %" PRId64 " = cookie->io\n",
__func__, current_async, cookie->io);
}
switch (current_async) {
@@ -840,7 +840,7 @@ static void interface_update_area_complete(QXLInstance *sin,
static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
- QXLCookie *cookie = (QXLCookie *)cookie_token;
+ QXLCookie *cookie = (QXLCookie *)(uintptr_t)cookie_token;
switch (cookie->type) {
case QXL_COOKIE_TYPE_IO:
--
1.7.10

View File

@ -0,0 +1,67 @@
From 9f7bc0be9a5c353d076bb42b3bfdf77d8709063f Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Wed, 14 Mar 2012 20:33:37 +0200
Subject: [PATCH 428/434] spice: fix broken initialization
Commit 1b71f7c14fab6f00c2680d4489fbee7baf796e4f moved MODULE_INIT_QOM to
way before MODULE_INIT_MACHINE, thereby breaking assumptions made in
spice-core.c which registered both a type initializer and a machine
intializer.
This fix removes the type registration, and replaces it with calling
qemu_spice_init in vl.c after command line parsing (second pass) is
done, and after timers are armed, required by spice server.
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Conflicts:
ui/spice-core.c
---
ui/spice-core.c | 8 +-------
vl.c | 5 +++++
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 4ad0a67..a468524 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -554,7 +554,7 @@ void qemu_spice_init(void)
qemu_thread_get_self(&me);
- if (!opts) {
+ if (!opts) {
return;
}
port = qemu_opt_get_number(opts, "port", 0);
@@ -787,9 +787,3 @@ static void spice_register_config(void)
qemu_add_opts(&qemu_spice_opts);
}
machine_init(spice_register_config);
-
-static void spice_initialize(void)
-{
- qemu_spice_init();
-}
-device_init(spice_initialize);
diff --git a/vl.c b/vl.c
index fdefa86..d33eb03 100644
--- a/vl.c
+++ b/vl.c
@@ -3271,6 +3271,11 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
+#ifdef CONFIG_SPICE
+ /* spice needs the timers to be initialized by this point */
+ qemu_spice_init();
+#endif
+
if (icount_option && (kvm_enabled() || xen_enabled())) {
fprintf(stderr, "-icount is not allowed with kvm or xen\n");
exit(1);
--
1.7.10

View File

@ -0,0 +1,56 @@
From 2b4d2ccd83280b22d2fea0801e11af5a944a135d Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Wed, 7 Mar 2012 13:36:48 +0000
Subject: [PATCH 429/434] ui/spice-display.c: Fix compilation warnings on 32
bit hosts
Fix compilation failures ("cast from pointer to integer of
different size [-Werror=pointer-to-int-cast]") by using
uintptr_t instead.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
ui/spice-display.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 28d6d4a..6d7563f 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -80,8 +80,8 @@ void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
if (async != QXL_SYNC) {
spice_qxl_add_memslot_async(&ssd->qxl, memslot,
- (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
- QXL_IO_MEMSLOT_ADD_ASYNC));
+ (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_MEMSLOT_ADD_ASYNC));
} else {
ssd->worker->add_memslot(ssd->worker, memslot);
}
@@ -100,8 +100,8 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
trace_qemu_spice_create_primary_surface(ssd->qxl.id, id, surface, async);
if (async != QXL_SYNC) {
spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface,
- (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
- QXL_IO_CREATE_PRIMARY_ASYNC));
+ (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_CREATE_PRIMARY_ASYNC));
} else {
ssd->worker->create_primary_surface(ssd->worker, id, surface);
}
@@ -113,8 +113,8 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
trace_qemu_spice_destroy_primary_surface(ssd->qxl.id, id, async);
if (async != QXL_SYNC) {
spice_qxl_destroy_primary_surface_async(&ssd->qxl, id,
- (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
- QXL_IO_DESTROY_PRIMARY_ASYNC));
+ (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_DESTROY_PRIMARY_ASYNC));
} else {
ssd->worker->destroy_primary_surface(ssd->worker, id);
}
--
1.7.10

View File

@ -0,0 +1,78 @@
From 626eb7b96445815945600895a411ee14c10b9056 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Wed, 21 Mar 2012 18:17:18 +0200
Subject: [PATCH 430/434] ui/spice-display: use uintptr_t when casting qxl
physical addresses
The current intptr_t casts are a problem when the address's highest
bit is 1, and it is cast to a intptr_t and then to uint64_t, such
as at:
surface.mem = (intptr_t)ssd->buf;
This causes the sign bit to be extended which causes a wrong address to
be passed on to spice, which then complains when it gets the wrong
slot_id number, since the slot_id is taken from the higher bits.
The assertion happens early - during the first primary surface creation.
This fixes running "-vga qxl -spice" with 32 bit compiled
qemu-system-i386.
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
ui/spice-display.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 6d7563f..cb8a7ad 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -168,7 +168,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
drawable->bbox = ssd->dirty;
drawable->clip.type = SPICE_CLIP_TYPE_NONE;
drawable->effect = QXL_EFFECT_OPAQUE;
- drawable->release_info.id = (intptr_t)update;
+ drawable->release_info.id = (uintptr_t)update;
drawable->type = QXL_DRAW_COPY;
drawable->surfaces_dest[0] = -1;
drawable->surfaces_dest[1] = -1;
@@ -179,7 +179,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+ time_space.tv_nsec / 1000 / 1000;
drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT;
- drawable->u.copy.src_bitmap = (intptr_t)image;
+ drawable->u.copy.src_bitmap = (uintptr_t)image;
drawable->u.copy.src_area.right = bw;
drawable->u.copy.src_area.bottom = bh;
@@ -189,7 +189,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
image->bitmap.stride = bw * 4;
image->descriptor.width = image->bitmap.x = bw;
image->descriptor.height = image->bitmap.y = bh;
- image->bitmap.data = (intptr_t)(update->bitmap);
+ image->bitmap.data = (uintptr_t)(update->bitmap);
image->bitmap.palette = 0;
image->bitmap.format = SPICE_BITMAP_FMT_32BIT;
@@ -210,7 +210,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
}
cmd->type = QXL_CMD_DRAW;
- cmd->data = (intptr_t)drawable;
+ cmd->data = (uintptr_t)drawable;
memset(&ssd->dirty, 0, sizeof(ssd->dirty));
return update;
@@ -254,7 +254,7 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
surface.mouse_mode = true;
surface.flags = 0;
surface.type = 0;
- surface.mem = (intptr_t)ssd->buf;
+ surface.mem = (uintptr_t)ssd->buf;
surface.group_id = MEMSLOT_GROUP_HOST;
qemu_spice_create_primary_surface(ssd, 0, &surface, QXL_SYNC);
--
1.7.10

View File

@ -0,0 +1,185 @@
From f1e729a041efbd2d562e8202407e927745210bbd Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 14 Oct 2011 18:05:48 +0200
Subject: [PATCH 431/434] qxl: add optinal 64bit vram bar
This patch adds an 64bit pci bar for vram. It is turned off by default.
It can be enabled by setting the size of the 64bit bar to be larger than
the 32bit bar. Both 32bit and 64bit bar refer to the same memory. Only
the first part of the memory is available via 32bit bar.
The intention is to allow large vram sizes for 64bit guests, by allowing
the vram bar being mapped above 4G, so we don't have to squeeze it into
the pci I/O window below 4G.
With vram_size_mb=16 and vram64_size_mb=256 it looks like this:
00:02.0 VGA compatible controller: Red Hat, Inc. Device 0100 (rev 02) (prog-if 00 [VGA controller])
Subsystem: Red Hat, Inc Device 1100
Physical Slot: 2
Flags: fast devsel, IRQ 10
Memory at f8000000 (32-bit, non-prefetchable) [size=64M]
Memory at fc000000 (32-bit, non-prefetchable) [size=16M]
Memory at fd020000 (32-bit, non-prefetchable) [size=8K]
I/O ports at c5a0 [size=32]
Memory at ffe0000000 (64-bit, prefetchable) [size=256M]
Expansion ROM at fd000000 [disabled] [size=64K]
[ mapping above 4G needs patched seabios:
http://www.kraxel.org/cgit/seabios/commit/?h=pci64 ]
Conflicts:
hw/qxl.c
---
hw/qxl.c | 51 ++++++++++++++++++++++++++++++++++++++++++++-------
hw/qxl.h | 7 +++++++
2 files changed, 51 insertions(+), 7 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index bcdf274..18f3759 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1002,6 +1002,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
static const int regions[] = {
QXL_RAM_RANGE_INDEX,
QXL_VRAM_RANGE_INDEX,
+ QXL_VRAM64_RANGE_INDEX,
};
uint64_t guest_start;
uint64_t guest_end;
@@ -1046,6 +1047,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vga.vram);
break;
case QXL_VRAM_RANGE_INDEX:
+ case 4 /* vram 64bit */:
virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vram_bar);
break;
default:
@@ -1630,18 +1632,28 @@ static void qxl_init_ramsize(PCIQXLDevice *qxl, uint32_t ram_min_mb)
qxl->vga.vram_size = ram_min_mb * 1024 * 1024;
}
- /* vram (surfaces, bar 1) */
+ /* vram32 (surfaces, 32bit, bar 1) */
+ if (qxl->vram32_size_mb != -1) {
+ qxl->vram32_size = qxl->vram32_size_mb * 1024 * 1024;
+ }
+ if (qxl->vram32_size < 4096) {
+ qxl->vram32_size = 4096;
+ }
+
+ /* vram (surfaces, 64bit, bar 4+5) */
if (qxl->vram_size_mb != -1) {
qxl->vram_size = qxl->vram_size_mb * 1024 * 1024;
}
- if (qxl->vram_size < 4096) {
- qxl->vram_size = 4096;
+ if (qxl->vram_size < qxl->vram32_size) {
+ qxl->vram_size = qxl->vram32_size;
}
+
if (qxl->revision == 1) {
+ qxl->vram32_size = 4096;
qxl->vram_size = 4096;
}
-
qxl->vga.vram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
+ qxl->vram32_size = msb_mask(qxl->vram32_size * 2 - 1);
qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
}
@@ -1683,6 +1695,8 @@ static int qxl_init_common(PCIQXLDevice *qxl)
memory_region_init_ram(&qxl->vram_bar, &qxl->pci.qdev, "qxl.vram",
qxl->vram_size);
+ memory_region_init_alias(&qxl->vram32_bar, "qxl.vram32", &qxl->vram_bar,
+ 0, qxl->vram32_size);
io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
if (qxl->revision == 1) {
@@ -1706,7 +1720,29 @@ static int qxl_init_common(PCIQXLDevice *qxl)
PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vga.vram);
pci_register_bar(&qxl->pci, QXL_VRAM_RANGE_INDEX,
- PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vram_bar);
+ PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vram32_bar);
+
+ if (qxl->vram32_size < qxl->vram_size) {
+ /*
+ * Make the 64bit vram bar show up only in case it is
+ * configured to be larger than the 32bit vram bar.
+ */
+ pci_register_bar(&qxl->pci, QXL_VRAM64_RANGE_INDEX,
+ PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64 |
+ PCI_BASE_ADDRESS_MEM_PREFETCH,
+ &qxl->vram_bar);
+ }
+
+ /* print pci bar details */
+ dprint(qxl, 1, "ram/%s: %d MB [region 0]\n",
+ qxl->id == 0 ? "pri" : "sec",
+ qxl->vga.vram_size / (1024*1024));
+ dprint(qxl, 1, "vram/32: %d MB [region 1]\n",
+ qxl->vram32_size / (1024*1024));
+ dprint(qxl, 1, "vram/64: %d MB %s\n",
+ qxl->vram_size / (1024*1024),
+ qxl->vram32_size < qxl->vram_size ? "[region 4]" : "[unmapped]");
qxl->ssd.qxl.base.sif = &qxl_interface.base;
qxl->ssd.qxl.id = qxl->id;
@@ -1918,7 +1954,7 @@ static VMStateDescription qxl_vmstate = {
static Property qxl_properties[] = {
DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
64 * 1024 * 1024),
- DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size,
+ DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram32_size,
64 * 1024 * 1024),
DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
QXL_DEFAULT_REVISION),
@@ -1926,7 +1962,8 @@ static Property qxl_properties[] = {
DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
DEFINE_PROP_UINT32("ram_size_mb", PCIQXLDevice, ram_size_mb, -1),
- DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram_size_mb, -1),
+ DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram32_size_mb, 0),
+ DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, 0),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/qxl.h b/hw/qxl.h
index 86e415b..11a0db3 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -16,6 +16,10 @@ enum qxl_mode {
QXL_MODE_NATIVE,
};
+#ifndef QXL_VRAM64_RANGE_INDEX
+#define QXL_VRAM64_RANGE_INDEX 4
+#endif
+
#define QXL_UNDEFINED_IO UINT32_MAX
#define QXL_NUM_DIRTY_RECTS 64
@@ -88,6 +92,8 @@ typedef struct PCIQXLDevice {
/* vram pci bar */
uint32_t vram_size;
MemoryRegion vram_bar;
+ uint32_t vram32_size;
+ MemoryRegion vram32_bar;
/* io bar */
MemoryRegion io_bar;
@@ -95,6 +101,7 @@ typedef struct PCIQXLDevice {
/* user-friendly properties (in megabytes) */
uint32_t ram_size_mb;
uint32_t vram_size_mb;
+ uint32_t vram32_size_mb;
/* qxl_render_update state */
int render_update_cookie_num;
--
1.7.10

View File

@ -0,0 +1,35 @@
From c18b8163ec4ebec3a7f99865038fa1ad36b2add2 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Thu, 29 Mar 2012 22:24:38 +0200
Subject: [PATCH 432/434] qxl: set default values of vram*_size_mb to -1
The addition of those values caused a regression where not specifying
any value for the vram bar size would result in a 4096 _byte_ surface
area. This is ok for the windows driver but causes the X driver to be
unusable. Also, it's a regression. This patch returns the default
behavior of having a 64 megabyte vram BAR.
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/qxl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 18f3759..2135fde 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1962,8 +1962,8 @@ static Property qxl_properties[] = {
DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
DEFINE_PROP_UINT32("ram_size_mb", PCIQXLDevice, ram_size_mb, -1),
- DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram32_size_mb, 0),
- DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, 0),
+ DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram32_size_mb, -1),
+ DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1),
DEFINE_PROP_END_OF_LIST(),
};
--
1.7.10

View File

@ -0,0 +1,30 @@
From 68fc3d666b28d14c5023c1f2115cd3a51389f838 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Wed, 18 Apr 2012 12:24:28 +0300
Subject: [PATCH 433/434] qxl-render: fix broken vnc+spice since commit
f934493
Notify any listeners such as vnc that the displaysurface has been
changed, otherwise they will segfault when first accessing the freed old
displaysurface data.
Signed-off-by: Alon Levy <alevy@redhat.com>
---
hw/qxl-render.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 835dc5e..180b8f9 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -127,6 +127,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qemu_resize_displaysurface(vga->ds,
qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height);
+ dpy_resize(vga->ds);
}
}
for (i = 0; i < qxl->num_dirty_rects; i++) {
--
1.7.10

View File

@ -0,0 +1,36 @@
From f9f547a6646d72204d88a79960191a0285774c23 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Wed, 18 Apr 2012 14:00:06 +0300
Subject: [PATCH 434/434] qxl: don't assert on guest create_guest_primary
initiate the implicit destroy ourselves.
Signed-off-by: Alon Levy <alevy@redhat.com>
---
hw/qxl.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 2135fde..29c8873 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1123,7 +1123,15 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
QXLDevSurfaceCreate surface;
QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
- assert(qxl->mode != QXL_MODE_NATIVE);
+ if (qxl->mode == QXL_MODE_NATIVE) {
+ /*
+ * allow a create without a destroy. This could be used
+ * later for an atomic "change primary" but right now just
+ * destroy the primary for the guest. Note that this uses
+ * the ability to have multiple concurrent async commands.
+ */
+ qxl_destroy_primary(qxl, async);
+ }
qxl_exit_vga_mode(qxl);
surface.format = le32_to_cpu(sc->format);
--
1.7.10

View File

@ -0,0 +1,68 @@
From be81272bafb948278e5e5739ef975cd7bbf0ee0c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
Date: Tue, 17 Apr 2012 14:32:35 +0200
Subject: [PATCH 501/509] audio: add VOICE_VOLUME ctl
Add a new PCM control operation to update the stream volume on the
audio backend. The argument given is a SWVoiceOut/SWVoiceIn.
v4:
- verified other backends didn't fail/assert on this new control
they randomly return 0 or -1, but we ignore return value.
Signed-off-by: Marc-Andr? Lureau <marcandre.lureau@redhat.com>
Signed-off-by: malc <av1474@comtv.ru>
---
audio/audio.c | 12 ++++++++++++
audio/audio_int.h | 1 +
2 files changed, 13 insertions(+)
diff --git a/audio/audio.c b/audio/audio.c
index 50d0d71..2ae9b2f 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -2050,17 +2050,29 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol)
{
if (sw) {
+ HWVoiceOut *hw = sw->hw;
+
sw->vol.mute = mute;
sw->vol.l = nominal_volume.l * lvol / 255;
sw->vol.r = nominal_volume.r * rvol / 255;
+
+ if (hw->pcm_ops->ctl_out) {
+ hw->pcm_ops->ctl_out (hw, VOICE_VOLUME, sw);
+ }
}
}
void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol)
{
if (sw) {
+ HWVoiceIn *hw = sw->hw;
+
sw->vol.mute = mute;
sw->vol.l = nominal_volume.l * lvol / 255;
sw->vol.r = nominal_volume.r * rvol / 255;
+
+ if (hw->pcm_ops->ctl_in) {
+ hw->pcm_ops->ctl_in (hw, VOICE_VOLUME, sw);
+ }
}
}
diff --git a/audio/audio_int.h b/audio/audio_int.h
index 2003f8b..117f95e 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -231,6 +231,7 @@ void audio_run (const char *msg);
#define VOICE_ENABLE 1
#define VOICE_DISABLE 2
+#define VOICE_VOLUME 3
static inline int audio_ring_dist (int dst, int src, int len)
{
--
1.7.10

View File

@ -0,0 +1,99 @@
From eaa3b2d4cc2ac17b2aaf0d6387d3991b9d08c56e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
Date: Tue, 17 Apr 2012 14:32:36 +0200
Subject: [PATCH 502/509] audio: don't apply volume effect if backend has
VOICE_VOLUME_CAP
If the audio backend is capable of volume control, don't apply
software volume (mixeng_volume ()), but instead, rely on backend
volume control. This will allow guest to have full range volume
control.
Signed-off-by: Marc-Andr? Lureau <marcandre.lureau@redhat.com>
Signed-off-by: malc <av1474@comtv.ru>
---
audio/audio.c | 9 +++++++--
audio/audio_int.h | 5 +++++
audio/audio_template.h | 2 ++
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/audio/audio.c b/audio/audio.c
index 2ae9b2f..0fe95a7 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -954,7 +954,9 @@ int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size)
total += isamp;
}
- mixeng_volume (sw->buf, ret, &sw->vol);
+ if (!(hw->ctl_caps & VOICE_VOLUME_CAP)) {
+ mixeng_volume (sw->buf, ret, &sw->vol);
+ }
sw->clip (buf, sw->buf, ret);
sw->total_hw_samples_acquired += total;
@@ -1038,7 +1040,10 @@ int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)
swlim = audio_MIN (swlim, samples);
if (swlim) {
sw->conv (sw->buf, buf, swlim);
- mixeng_volume (sw->buf, swlim, &sw->vol);
+
+ if (!(sw->hw->ctl_caps & VOICE_VOLUME_CAP)) {
+ mixeng_volume (sw->buf, swlim, &sw->vol);
+ }
}
while (swlim) {
diff --git a/audio/audio_int.h b/audio/audio_int.h
index 117f95e..b9b0676 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -82,6 +82,7 @@ typedef struct HWVoiceOut {
int samples;
QLIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head;
QLIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head;
+ int ctl_caps;
struct audio_pcm_ops *pcm_ops;
QLIST_ENTRY (HWVoiceOut) entries;
} HWVoiceOut;
@@ -101,6 +102,7 @@ typedef struct HWVoiceIn {
int samples;
QLIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head;
+ int ctl_caps;
struct audio_pcm_ops *pcm_ops;
QLIST_ENTRY (HWVoiceIn) entries;
} HWVoiceIn;
@@ -150,6 +152,7 @@ struct audio_driver {
int max_voices_in;
int voice_size_out;
int voice_size_in;
+ int ctl_caps;
};
struct audio_pcm_ops {
@@ -233,6 +236,8 @@ void audio_run (const char *msg);
#define VOICE_DISABLE 2
#define VOICE_VOLUME 3
+#define VOICE_VOLUME_CAP (1 << VOICE_VOLUME)
+
static inline int audio_ring_dist (int dst, int src, int len)
{
return (dst >= src) ? (dst - src) : (len - src + dst);
diff --git a/audio/audio_template.h b/audio/audio_template.h
index e62a713..519432a 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -263,6 +263,8 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (struct audsettings *as)
}
hw->pcm_ops = drv->pcm_ops;
+ hw->ctl_caps = drv->ctl_caps;
+
QLIST_INIT (&hw->sw_head);
#ifdef DAC
QLIST_INIT (&hw->cap_head);
--
1.7.10

View File

@ -0,0 +1,170 @@
From e27e5ceeee3d8cb55ba0749446b49ccc6ec5b96d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
Date: Tue, 17 Apr 2012 14:32:37 +0200
Subject: [PATCH 503/509] hw/ac97: remove USE_MIXER code
That code doesn't compile. The interesting bits for volume control are
going to be rewritten in the following patch.
Signed-off-by: Marc-Andr? Lureau <marcandre.lureau@redhat.com>
Signed-off-by: malc <av1474@comtv.ru>
---
hw/ac97.c | 121 -------------------------------------------------------------
1 file changed, 121 deletions(-)
diff --git a/hw/ac97.c b/hw/ac97.c
index 0dbba3b..cd893c3 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -434,99 +434,6 @@ static void reset_voices (AC97LinkState *s, uint8_t active[LAST_INDEX])
AUD_set_active_in (s->voice_mc, active[MC_INDEX]);
}
-#ifdef USE_MIXER
-static void set_volume (AC97LinkState *s, int index,
- audmixerctl_t mt, uint32_t val)
-{
- int mute = (val >> MUTE_SHIFT) & 1;
- uint8_t rvol = VOL_MASK - (val & VOL_MASK);
- uint8_t lvol = VOL_MASK - ((val >> 8) & VOL_MASK);
- rvol = 255 * rvol / VOL_MASK;
- lvol = 255 * lvol / VOL_MASK;
-
-#ifdef SOFT_VOLUME
- if (index == AC97_Master_Volume_Mute) {
- AUD_set_volume_out (s->voice_po, mute, lvol, rvol);
- }
- else {
- AUD_set_volume (mt, &mute, &lvol, &rvol);
- }
-#else
- AUD_set_volume (mt, &mute, &lvol, &rvol);
-#endif
-
- rvol = VOL_MASK - ((VOL_MASK * rvol) / 255);
- lvol = VOL_MASK - ((VOL_MASK * lvol) / 255);
- mixer_store (s, index, val);
-}
-
-static audrecsource_t ac97_to_aud_record_source (uint8_t i)
-{
- switch (i) {
- case REC_MIC:
- return AUD_REC_MIC;
-
- case REC_CD:
- return AUD_REC_CD;
-
- case REC_VIDEO:
- return AUD_REC_VIDEO;
-
- case REC_AUX:
- return AUD_REC_AUX;
-
- case REC_LINE_IN:
- return AUD_REC_LINE_IN;
-
- case REC_PHONE:
- return AUD_REC_PHONE;
-
- default:
- dolog ("Unknown record source %d, using MIC\n", i);
- return AUD_REC_MIC;
- }
-}
-
-static uint8_t aud_to_ac97_record_source (audrecsource_t rs)
-{
- switch (rs) {
- case AUD_REC_MIC:
- return REC_MIC;
-
- case AUD_REC_CD:
- return REC_CD;
-
- case AUD_REC_VIDEO:
- return REC_VIDEO;
-
- case AUD_REC_AUX:
- return REC_AUX;
-
- case AUD_REC_LINE_IN:
- return REC_LINE_IN;
-
- case AUD_REC_PHONE:
- return REC_PHONE;
-
- default:
- dolog ("Unknown audio recording source %d using MIC\n", rs);
- return REC_MIC;
- }
-}
-
-static void record_select (AC97LinkState *s, uint32_t val)
-{
- uint8_t rs = val & REC_MASK;
- uint8_t ls = (val >> 8) & REC_MASK;
- audrecsource_t ars = ac97_to_aud_record_source (rs);
- audrecsource_t als = ac97_to_aud_record_source (ls);
- AUD_set_record_source (&als, &ars);
- rs = aud_to_ac97_record_source (ars);
- ls = aud_to_ac97_record_source (als);
- mixer_store (s, AC97_Record_Select, rs | (ls << 8));
-}
-#endif
-
static void mixer_reset (AC97LinkState *s)
{
uint8_t active[LAST_INDEX];
@@ -561,12 +468,6 @@ static void mixer_reset (AC97LinkState *s)
mixer_store (s, AC97_PCM_LR_ADC_Rate , 0xbb80);
mixer_store (s, AC97_MIC_ADC_Rate , 0xbb80);
-#ifdef USE_MIXER
- record_select (s, 0);
- set_volume (s, AC97_Master_Volume_Mute, AUD_MIXER_VOLUME , 0x8000);
- set_volume (s, AC97_PCM_Out_Volume_Mute, AUD_MIXER_PCM , 0x8808);
- set_volume (s, AC97_Line_In_Volume_Mute, AUD_MIXER_LINE_IN, 0x8808);
-#endif
reset_voices (s, active);
}
@@ -625,20 +526,6 @@ static void nam_writew (void *opaque, uint32_t addr, uint32_t val)
val |= mixer_load (s, index) & 0xf;
mixer_store (s, index, val);
break;
-#ifdef USE_MIXER
- case AC97_Master_Volume_Mute:
- set_volume (s, index, AUD_MIXER_VOLUME, val);
- break;
- case AC97_PCM_Out_Volume_Mute:
- set_volume (s, index, AUD_MIXER_PCM, val);
- break;
- case AC97_Line_In_Volume_Mute:
- set_volume (s, index, AUD_MIXER_LINE_IN, val);
- break;
- case AC97_Record_Select:
- record_select (s, val);
- break;
-#endif
case AC97_Vendor_ID1:
case AC97_Vendor_ID2:
dolog ("Attempt to write vendor ID to %#x\n", val);
@@ -1191,14 +1078,6 @@ static int ac97_post_load (void *opaque, int version_id)
uint8_t active[LAST_INDEX];
AC97LinkState *s = opaque;
-#ifdef USE_MIXER
- record_select (s, mixer_load (s, AC97_Record_Select));
-#define V_(a, b) set_volume (s, a, b, mixer_load (s, a))
- V_ (AC97_Master_Volume_Mute, AUD_MIXER_VOLUME);
- V_ (AC97_PCM_Out_Volume_Mute, AUD_MIXER_PCM);
- V_ (AC97_Line_In_Volume_Mute, AUD_MIXER_LINE_IN);
-#undef V_
-#endif
active[PI_INDEX] = !!(s->bm_regs[PI_INDEX].cr & CR_RPBM);
active[PO_INDEX] = !!(s->bm_regs[PO_INDEX].cr & CR_RPBM);
active[MC_INDEX] = !!(s->bm_regs[MC_INDEX].cr & CR_RPBM);
--
1.7.10

View File

@ -0,0 +1,28 @@
From c0bcb346459445db2895fb56c78ab71e592c0c90 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
Date: Tue, 17 Apr 2012 14:32:38 +0200
Subject: [PATCH 504/509] hw/ac97: the volume mask is not only 0x1f
It's a case by case (see Table 66. AC ?97 Baseline Audio Register Map)
Signed-off-by: Marc-Andr? Lureau <marcandre.lureau@redhat.com>
Signed-off-by: malc <av1474@comtv.ru>
---
hw/ac97.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/hw/ac97.c b/hw/ac97.c
index cd893c3..aa1babf 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -115,7 +115,6 @@ enum {
#define EACS_VRA 1
#define EACS_VRM 8
-#define VOL_MASK 0x1f
#define MUTE_SHIFT 15
#define REC_MASK 7
--
1.7.10

View File

@ -0,0 +1,134 @@
From 41d13bd2047a3a3ae8f451ff4aaf0585231ba1c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
Date: Tue, 17 Apr 2012 14:32:39 +0200
Subject: [PATCH 505/509] hw/ac97: add support for volume control
Combine output volume with Master and PCM registers values.
Use default values in mixer_reset ().
Set volume on post-load to update backend values.
v4,v5:
- fix some code style
Signed-off-by: Marc-Andr? Lureau <marcandre.lureau@redhat.com>
Signed-off-by: malc <av1474@comtv.ru>
---
hw/ac97.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/hw/ac97.c b/hw/ac97.c
index aa1babf..dd4917b 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -433,6 +433,65 @@ static void reset_voices (AC97LinkState *s, uint8_t active[LAST_INDEX])
AUD_set_active_in (s->voice_mc, active[MC_INDEX]);
}
+static void get_volume (uint16_t vol, uint16_t mask, int inverse,
+ int *mute, uint8_t *lvol, uint8_t *rvol)
+{
+ *mute = (vol >> MUTE_SHIFT) & 1;
+ *rvol = (255 * (vol & mask)) / mask;
+ *lvol = (255 * ((vol >> 8) & mask)) / mask;
+
+ if (inverse) {
+ *rvol = 255 - *rvol;
+ *lvol = 255 - *lvol;
+ }
+}
+
+static void update_combined_volume_out (AC97LinkState *s)
+{
+ uint8_t lvol, rvol, plvol, prvol;
+ int mute, pmute;
+
+ get_volume (mixer_load (s, AC97_Master_Volume_Mute), 0x3f, 1,
+ &mute, &lvol, &rvol);
+ /* FIXME: should be 1f according to spec */
+ get_volume (mixer_load (s, AC97_PCM_Out_Volume_Mute), 0x3f, 1,
+ &pmute, &plvol, &prvol);
+
+ mute = mute | pmute;
+ lvol = (lvol * plvol) / 255;
+ rvol = (rvol * prvol) / 255;
+
+ AUD_set_volume_out (s->voice_po, mute, lvol, rvol);
+}
+
+static void update_volume_in (AC97LinkState *s)
+{
+ uint8_t lvol, rvol;
+ int mute;
+
+ get_volume (mixer_load (s, AC97_Record_Gain_Mute), 0x0f, 0,
+ &mute, &lvol, &rvol);
+
+ AUD_set_volume_in (s->voice_pi, mute, lvol, rvol);
+}
+
+static void set_volume (AC97LinkState *s, int index, uint32_t val)
+{
+ mixer_store (s, index, val);
+ if (index == AC97_Master_Volume_Mute || index == AC97_PCM_Out_Volume_Mute) {
+ update_combined_volume_out (s);
+ } else if (index == AC97_Record_Gain_Mute) {
+ update_volume_in (s);
+ }
+}
+
+static void record_select (AC97LinkState *s, uint32_t val)
+{
+ uint8_t rs = val & REC_MASK;
+ uint8_t ls = (val >> 8) & REC_MASK;
+ mixer_store (s, AC97_Record_Select, rs | (ls << 8));
+}
+
static void mixer_reset (AC97LinkState *s)
{
uint8_t active[LAST_INDEX];
@@ -467,6 +526,11 @@ static void mixer_reset (AC97LinkState *s)
mixer_store (s, AC97_PCM_LR_ADC_Rate , 0xbb80);
mixer_store (s, AC97_MIC_ADC_Rate , 0xbb80);
+ record_select (s, 0);
+ set_volume (s, AC97_Master_Volume_Mute, 0x8000);
+ set_volume (s, AC97_PCM_Out_Volume_Mute, 0x8808);
+ set_volume (s, AC97_Line_In_Volume_Mute, 0x8808);
+
reset_voices (s, active);
}
@@ -525,6 +589,15 @@ static void nam_writew (void *opaque, uint32_t addr, uint32_t val)
val |= mixer_load (s, index) & 0xf;
mixer_store (s, index, val);
break;
+ case AC97_PCM_Out_Volume_Mute:
+ case AC97_Master_Volume_Mute:
+ case AC97_Record_Gain_Mute:
+ case AC97_Line_In_Volume_Mute:
+ set_volume (s, index, val);
+ break;
+ case AC97_Record_Select:
+ record_select (s, val);
+ break;
case AC97_Vendor_ID1:
case AC97_Vendor_ID2:
dolog ("Attempt to write vendor ID to %#x\n", val);
@@ -1077,6 +1150,14 @@ static int ac97_post_load (void *opaque, int version_id)
uint8_t active[LAST_INDEX];
AC97LinkState *s = opaque;
+ record_select (s, mixer_load (s, AC97_Record_Select));
+ set_volume (s, AC97_Master_Volume_Mute,
+ mixer_load (s, AC97_Master_Volume_Mute));
+ set_volume (s, AC97_PCM_Out_Volume_Mute,
+ mixer_load (s, AC97_PCM_Out_Volume_Mute));
+ set_volume (s, AC97_Line_In_Volume_Mute,
+ mixer_load (s, AC97_Line_In_Volume_Mute));
+
active[PI_INDEX] = !!(s->bm_regs[PI_INDEX].cr & CR_RPBM);
active[PO_INDEX] = !!(s->bm_regs[PO_INDEX].cr & CR_RPBM);
active[MC_INDEX] = !!(s->bm_regs[MC_INDEX].cr & CR_RPBM);
--
1.7.10

View File

@ -0,0 +1,84 @@
From a9f796f670f3c34c3b5874026b61bbe4d782be2e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
Date: Tue, 17 Apr 2012 14:32:40 +0200
Subject: [PATCH 506/509] audio/spice: add support for volume control
Use Spice server volume control API when available.
Signed-off-by: Marc-Andr? Lureau <marcandre.lureau@redhat.com>
Signed-off-by: malc <av1474@comtv.ru>
---
audio/spiceaudio.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c
index f972110..6f15591 100644
--- a/audio/spiceaudio.c
+++ b/audio/spiceaudio.c
@@ -202,7 +202,26 @@ static int line_out_ctl (HWVoiceOut *hw, int cmd, ...)
}
spice_server_playback_stop (&out->sin);
break;
+ case VOICE_VOLUME:
+ {
+#if ((SPICE_INTERFACE_PLAYBACK_MAJOR >= 1) && (SPICE_INTERFACE_PLAYBACK_MINOR >= 2))
+ SWVoiceOut *sw;
+ va_list ap;
+ uint16_t vol[2];
+
+ va_start (ap, cmd);
+ sw = va_arg (ap, SWVoiceOut *);
+ va_end (ap);
+
+ vol[0] = sw->vol.l / ((1ULL << 16) + 1);
+ vol[1] = sw->vol.r / ((1ULL << 16) + 1);
+ spice_server_playback_set_volume (&out->sin, 2, vol);
+ spice_server_playback_set_mute (&out->sin, sw->vol.mute);
+#endif
+ break;
+ }
}
+
return 0;
}
@@ -304,7 +323,26 @@ static int line_in_ctl (HWVoiceIn *hw, int cmd, ...)
in->active = 0;
spice_server_record_stop (&in->sin);
break;
+ case VOICE_VOLUME:
+ {
+#if ((SPICE_INTERFACE_RECORD_MAJOR >= 2) && (SPICE_INTERFACE_RECORD_MINOR >= 2))
+ SWVoiceIn *sw;
+ va_list ap;
+ uint16_t vol[2];
+
+ va_start (ap, cmd);
+ sw = va_arg (ap, SWVoiceIn *);
+ va_end (ap);
+
+ vol[0] = sw->vol.l / ((1ULL << 16) + 1);
+ vol[1] = sw->vol.r / ((1ULL << 16) + 1);
+ spice_server_record_set_volume (&in->sin, 2, vol);
+ spice_server_record_set_mute (&in->sin, sw->vol.mute);
+#endif
+ break;
+ }
}
+
return 0;
}
@@ -337,6 +375,9 @@ struct audio_driver spice_audio_driver = {
.max_voices_in = 1,
.voice_size_out = sizeof (SpiceVoiceOut),
.voice_size_in = sizeof (SpiceVoiceIn),
+#if ((SPICE_INTERFACE_PLAYBACK_MAJOR >= 1) && (SPICE_INTERFACE_PLAYBACK_MINOR >= 2))
+ .ctl_caps = VOICE_VOLUME_CAP
+#endif
};
void qemu_spice_audio_init (void)
--
1.7.10

View File

@ -0,0 +1,573 @@
From 5c8ce128ec78d17a8a0f49115dc07726a3d3f0c1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
Date: Tue, 17 Apr 2012 14:32:41 +0200
Subject: [PATCH 507/509] Do not use pa_simple PulseAudio API
Unfortunately, pa_simple is a limited API which doesn't let us
retrieve the associated pa_stream. It is needed to control the volume
of the stream.
In v4:
- add missing braces
Signed-off-by: Marc-Andr? Lureau <marcandre.lureau@redhat.com>
Signed-off-by: malc <av1474@comtv.ru>
---
audio/paaudio.c | 377 +++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 339 insertions(+), 38 deletions(-)
diff --git a/audio/paaudio.c b/audio/paaudio.c
index d1f3912..6f50c1c 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -2,8 +2,7 @@
#include "qemu-common.h"
#include "audio.h"
-#include <pulse/simple.h>
-#include <pulse/error.h>
+#include <pulse/pulseaudio.h>
#define AUDIO_CAP "pulseaudio"
#include "audio_int.h"
@@ -15,7 +14,7 @@ typedef struct {
int live;
int decr;
int rpos;
- pa_simple *s;
+ pa_stream *stream;
void *pcm_buf;
struct audio_pt pt;
} PAVoiceOut;
@@ -26,17 +25,23 @@ typedef struct {
int dead;
int incr;
int wpos;
- pa_simple *s;
+ pa_stream *stream;
void *pcm_buf;
struct audio_pt pt;
+ const void *read_data;
+ size_t read_index, read_length;
} PAVoiceIn;
-static struct {
+typedef struct {
int samples;
char *server;
char *sink;
char *source;
-} conf = {
+ pa_threaded_mainloop *mainloop;
+ pa_context *context;
+} paaudio;
+
+static paaudio glob_paaudio = {
.samples = 4096,
};
@@ -51,6 +56,126 @@ static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...)
AUD_log (AUDIO_CAP, "Reason: %s\n", pa_strerror (err));
}
+#define CHECK_SUCCESS_GOTO(c, rerror, expression, label) \
+ do { \
+ if (!(expression)) { \
+ if (rerror) { \
+ *(rerror) = pa_context_errno ((c)->context); \
+ } \
+ goto label; \
+ } \
+ } while (0);
+
+#define CHECK_DEAD_GOTO(c, stream, rerror, label) \
+ do { \
+ if (!(c)->context || !PA_CONTEXT_IS_GOOD (pa_context_get_state((c)->context)) || \
+ !(stream) || !PA_STREAM_IS_GOOD (pa_stream_get_state ((stream)))) { \
+ if (((c)->context && pa_context_get_state ((c)->context) == PA_CONTEXT_FAILED) || \
+ ((stream) && pa_stream_get_state ((stream)) == PA_STREAM_FAILED)) { \
+ if (rerror) { \
+ *(rerror) = pa_context_errno ((c)->context); \
+ } \
+ } else { \
+ if (rerror) { \
+ *(rerror) = PA_ERR_BADSTATE; \
+ } \
+ } \
+ goto label; \
+ } \
+ } while (0);
+
+static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror)
+{
+ paaudio *g = &glob_paaudio;
+
+ pa_threaded_mainloop_lock (g->mainloop);
+
+ CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail);
+
+ while (length > 0) {
+ size_t l;
+
+ while (!p->read_data) {
+ int r;
+
+ r = pa_stream_peek (p->stream, &p->read_data, &p->read_length);
+ CHECK_SUCCESS_GOTO (g, rerror, r == 0, unlock_and_fail);
+
+ if (!p->read_data) {
+ pa_threaded_mainloop_wait (g->mainloop);
+ CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail);
+ } else {
+ p->read_index = 0;
+ }
+ }
+
+ l = p->read_length < length ? p->read_length : length;
+ memcpy (data, (const uint8_t *) p->read_data+p->read_index, l);
+
+ data = (uint8_t *) data + l;
+ length -= l;
+
+ p->read_index += l;
+ p->read_length -= l;
+
+ if (!p->read_length) {
+ int r;
+
+ r = pa_stream_drop (p->stream);
+ p->read_data = NULL;
+ p->read_length = 0;
+ p->read_index = 0;
+
+ CHECK_SUCCESS_GOTO (g, rerror, r == 0, unlock_and_fail);
+ }
+ }
+
+ pa_threaded_mainloop_unlock (g->mainloop);
+ return 0;
+
+unlock_and_fail:
+ pa_threaded_mainloop_unlock (g->mainloop);
+ return -1;
+}
+
+static int qpa_simple_write (PAVoiceOut *p, const void *data, size_t length, int *rerror)
+{
+ paaudio *g = &glob_paaudio;
+
+ pa_threaded_mainloop_lock (g->mainloop);
+
+ CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail);
+
+ while (length > 0) {
+ size_t l;
+ int r;
+
+ while (!(l = pa_stream_writable_size (p->stream))) {
+ pa_threaded_mainloop_wait (g->mainloop);
+ CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail);
+ }
+
+ CHECK_SUCCESS_GOTO (g, rerror, l != (size_t) -1, unlock_and_fail);
+
+ if (l > length) {
+ l = length;
+ }
+
+ r = pa_stream_write (p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE);
+ CHECK_SUCCESS_GOTO (g, rerror, r >= 0, unlock_and_fail);
+
+ data = (const uint8_t *) data + l;
+ length -= l;
+ }
+
+ pa_threaded_mainloop_unlock (g->mainloop);
+ return 0;
+
+unlock_and_fail:
+ pa_threaded_mainloop_unlock (g->mainloop);
+ return -1;
+}
+
static void *qpa_thread_out (void *arg)
{
PAVoiceOut *pa = arg;
@@ -77,7 +202,7 @@ static void *qpa_thread_out (void *arg)
}
}
- decr = to_mix = audio_MIN (pa->live, conf.samples >> 2);
+ decr = to_mix = audio_MIN (pa->live, glob_paaudio.samples >> 2);
rpos = pa->rpos;
if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
@@ -91,8 +216,8 @@ static void *qpa_thread_out (void *arg)
hw->clip (pa->pcm_buf, src, chunk);
- if (pa_simple_write (pa->s, pa->pcm_buf,
- chunk << hw->info.shift, &error) < 0) {
+ if (qpa_simple_write (pa, pa->pcm_buf,
+ chunk << hw->info.shift, &error) < 0) {
qpa_logerr (error, "pa_simple_write failed\n");
return NULL;
}
@@ -169,7 +294,7 @@ static void *qpa_thread_in (void *arg)
}
}
- incr = to_grab = audio_MIN (pa->dead, conf.samples >> 2);
+ incr = to_grab = audio_MIN (pa->dead, glob_paaudio.samples >> 2);
wpos = pa->wpos;
if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
@@ -181,8 +306,8 @@ static void *qpa_thread_in (void *arg)
int chunk = audio_MIN (to_grab, hw->samples - wpos);
void *buf = advance (pa->pcm_buf, wpos);
- if (pa_simple_read (pa->s, buf,
- chunk << hw->info.shift, &error) < 0) {
+ if (qpa_simple_read (pa, buf,
+ chunk << hw->info.shift, &error) < 0) {
qpa_logerr (error, "pa_simple_read failed\n");
return NULL;
}
@@ -283,6 +408,109 @@ static audfmt_e pa_to_audfmt (pa_sample_format_t fmt, int *endianness)
}
}
+static void context_state_cb (pa_context *c, void *userdata)
+{
+ paaudio *g = &glob_paaudio;
+
+ switch (pa_context_get_state(c)) {
+ case PA_CONTEXT_READY:
+ case PA_CONTEXT_TERMINATED:
+ case PA_CONTEXT_FAILED:
+ pa_threaded_mainloop_signal (g->mainloop, 0);
+ break;
+
+ case PA_CONTEXT_UNCONNECTED:
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+ }
+}
+
+static void stream_state_cb (pa_stream *s, void * userdata)
+{
+ paaudio *g = &glob_paaudio;
+
+ switch (pa_stream_get_state (s)) {
+
+ case PA_STREAM_READY:
+ case PA_STREAM_FAILED:
+ case PA_STREAM_TERMINATED:
+ pa_threaded_mainloop_signal (g->mainloop, 0);
+ break;
+
+ case PA_STREAM_UNCONNECTED:
+ case PA_STREAM_CREATING:
+ break;
+ }
+}
+
+static void stream_request_cb (pa_stream *s, size_t length, void *userdata)
+{
+ paaudio *g = &glob_paaudio;
+
+ pa_threaded_mainloop_signal (g->mainloop, 0);
+}
+
+static pa_stream *qpa_simple_new (
+ const char *server,
+ const char *name,
+ pa_stream_direction_t dir,
+ const char *dev,
+ const char *stream_name,
+ const pa_sample_spec *ss,
+ const pa_channel_map *map,
+ const pa_buffer_attr *attr,
+ int *rerror)
+{
+ paaudio *g = &glob_paaudio;
+ int r;
+ pa_stream *stream;
+
+ pa_threaded_mainloop_lock (g->mainloop);
+
+ stream = pa_stream_new (g->context, name, ss, map);
+ if (!stream) {
+ goto fail;
+ }
+
+ pa_stream_set_state_callback (stream, stream_state_cb, g);
+ pa_stream_set_read_callback (stream, stream_request_cb, g);
+ pa_stream_set_write_callback (stream, stream_request_cb, g);
+
+ if (dir == PA_STREAM_PLAYBACK) {
+ r = pa_stream_connect_playback (stream, dev, attr,
+ PA_STREAM_INTERPOLATE_TIMING
+ |PA_STREAM_ADJUST_LATENCY
+ |PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
+ } else {
+ r = pa_stream_connect_record (stream, dev, attr,
+ PA_STREAM_INTERPOLATE_TIMING
+ |PA_STREAM_ADJUST_LATENCY
+ |PA_STREAM_AUTO_TIMING_UPDATE);
+ }
+
+ if (r < 0) {
+ goto fail;
+ }
+
+ pa_threaded_mainloop_unlock (g->mainloop);
+
+ return stream;
+
+fail:
+ pa_threaded_mainloop_unlock (g->mainloop);
+
+ if (stream) {
+ pa_stream_unref (stream);
+ }
+
+ qpa_logerr (pa_context_errno (g->context),
+ "stream_new() failed\n");
+
+ return NULL;
+}
+
static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
{
int error;
@@ -306,24 +534,24 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
- pa->s = pa_simple_new (
- conf.server,
+ pa->stream = qpa_simple_new (
+ glob_paaudio.server,
"qemu",
PA_STREAM_PLAYBACK,
- conf.sink,
+ glob_paaudio.sink,
"pcm.playback",
&ss,
NULL, /* channel map */
&ba, /* buffering attributes */
&error
);
- if (!pa->s) {
+ if (!pa->stream) {
qpa_logerr (error, "pa_simple_new for playback failed\n");
goto fail1;
}
audio_pcm_init_info (&hw->info, &obt_as);
- hw->samples = conf.samples;
+ hw->samples = glob_paaudio.samples;
pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
pa->rpos = hw->rpos;
if (!pa->pcm_buf) {
@@ -342,8 +570,10 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
g_free (pa->pcm_buf);
pa->pcm_buf = NULL;
fail2:
- pa_simple_free (pa->s);
- pa->s = NULL;
+ if (pa->stream) {
+ pa_stream_unref (pa->stream);
+ pa->stream = NULL;
+ }
fail1:
return -1;
}
@@ -361,24 +591,24 @@ static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as)
obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
- pa->s = pa_simple_new (
- conf.server,
+ pa->stream = qpa_simple_new (
+ glob_paaudio.server,
"qemu",
PA_STREAM_RECORD,
- conf.source,
+ glob_paaudio.source,
"pcm.capture",
&ss,
NULL, /* channel map */
NULL, /* buffering attributes */
&error
);
- if (!pa->s) {
+ if (!pa->stream) {
qpa_logerr (error, "pa_simple_new for capture failed\n");
goto fail1;
}
audio_pcm_init_info (&hw->info, &obt_as);
- hw->samples = conf.samples;
+ hw->samples = glob_paaudio.samples;
pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
pa->wpos = hw->wpos;
if (!pa->pcm_buf) {
@@ -397,8 +627,10 @@ static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as)
g_free (pa->pcm_buf);
pa->pcm_buf = NULL;
fail2:
- pa_simple_free (pa->s);
- pa->s = NULL;
+ if (pa->stream) {
+ pa_stream_unref (pa->stream);
+ pa->stream = NULL;
+ }
fail1:
return -1;
}
@@ -413,9 +645,9 @@ static void qpa_fini_out (HWVoiceOut *hw)
audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
audio_pt_join (&pa->pt, &ret, AUDIO_FUNC);
- if (pa->s) {
- pa_simple_free (pa->s);
- pa->s = NULL;
+ if (pa->stream) {
+ pa_stream_unref (pa->stream);
+ pa->stream = NULL;
}
audio_pt_fini (&pa->pt, AUDIO_FUNC);
@@ -433,9 +665,9 @@ static void qpa_fini_in (HWVoiceIn *hw)
audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
audio_pt_join (&pa->pt, &ret, AUDIO_FUNC);
- if (pa->s) {
- pa_simple_free (pa->s);
- pa->s = NULL;
+ if (pa->stream) {
+ pa_stream_unref (pa->stream);
+ pa->stream = NULL;
}
audio_pt_fini (&pa->pt, AUDIO_FUNC);
@@ -460,37 +692,106 @@ static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...)
/* common */
static void *qpa_audio_init (void)
{
- return &conf;
+ paaudio *g = &glob_paaudio;
+
+ g->mainloop = pa_threaded_mainloop_new ();
+ if (!g->mainloop) {
+ goto fail;
+ }
+
+ g->context = pa_context_new (pa_threaded_mainloop_get_api (g->mainloop), glob_paaudio.server);
+ if (!g->context) {
+ goto fail;
+ }
+
+ pa_context_set_state_callback (g->context, context_state_cb, g);
+
+ if (pa_context_connect (g->context, glob_paaudio.server, 0, NULL) < 0) {
+ qpa_logerr (pa_context_errno (g->context),
+ "pa_context_connect() failed\n");
+ goto fail;
+ }
+
+ pa_threaded_mainloop_lock (g->mainloop);
+
+ if (pa_threaded_mainloop_start (g->mainloop) < 0) {
+ goto unlock_and_fail;
+ }
+
+ for (;;) {
+ pa_context_state_t state;
+
+ state = pa_context_get_state (g->context);
+
+ if (state == PA_CONTEXT_READY) {
+ break;
+ }
+
+ if (!PA_CONTEXT_IS_GOOD (state)) {
+ qpa_logerr (pa_context_errno (g->context),
+ "Wrong context state\n");
+ goto unlock_and_fail;
+ }
+
+ /* Wait until the context is ready */
+ pa_threaded_mainloop_wait (g->mainloop);
+ }
+
+ pa_threaded_mainloop_unlock (g->mainloop);
+
+ return &glob_paaudio;
+
+unlock_and_fail:
+ pa_threaded_mainloop_unlock (g->mainloop);
+fail:
+ AUD_log (AUDIO_CAP, "Failed to initialize PA context");
+ return NULL;
}
static void qpa_audio_fini (void *opaque)
{
- (void) opaque;
+ paaudio *g = opaque;
+
+ if (g->mainloop) {
+ pa_threaded_mainloop_stop (g->mainloop);
+ }
+
+ if (g->context) {
+ pa_context_disconnect (g->context);
+ pa_context_unref (g->context);
+ g->context = NULL;
+ }
+
+ if (g->mainloop) {
+ pa_threaded_mainloop_free (g->mainloop);
+ }
+
+ g->mainloop = NULL;
}
struct audio_option qpa_options[] = {
{
.name = "SAMPLES",
.tag = AUD_OPT_INT,
- .valp = &conf.samples,
+ .valp = &glob_paaudio.samples,
.descr = "buffer size in samples"
},
{
.name = "SERVER",
.tag = AUD_OPT_STR,
- .valp = &conf.server,
+ .valp = &glob_paaudio.server,
.descr = "server address"
},
{
.name = "SINK",
.tag = AUD_OPT_STR,
- .valp = &conf.sink,
+ .valp = &glob_paaudio.sink,
.descr = "sink device name"
},
{
.name = "SOURCE",
.tag = AUD_OPT_STR,
- .valp = &conf.source,
+ .valp = &glob_paaudio.source,
.descr = "source device name"
},
{ /* End of list */ }
--
1.7.10

View File

@ -0,0 +1,31 @@
From 1b4ee5ccd426102b9ea415a8ce563bf96d7aa1f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
Date: Tue, 17 Apr 2012 14:32:42 +0200
Subject: [PATCH 508/509] configure: pa_simple is not needed anymore
Signed-off-by: Marc-Andr? Lureau <marcandre.lureau@redhat.com>
Signed-off-by: malc <av1474@comtv.ru>
---
configure | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/configure b/configure
index b03172c..4559836 100755
--- a/configure
+++ b/configure
@@ -1791,9 +1791,9 @@ for drv in $audio_drv_list; do
;;
pa)
- audio_drv_probe $drv pulse/simple.h "-lpulse-simple -lpulse" \
- "pa_simple *s = 0; pa_simple_free(s); return 0;"
- libs_softmmu="-lpulse -lpulse-simple $libs_softmmu"
+ audio_drv_probe $drv pulse/mainloop.h "-lpulse" \
+ "pa_mainloop *m = 0; pa_mainloop_free (m); return 0;"
+ libs_softmmu="-lpulse $libs_softmmu"
audio_pt_int="yes"
;;
--
1.7.10

View File

@ -0,0 +1,134 @@
From 4b09edbfdaad4536617bbb53ccadfe531156ed56 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
Date: Tue, 17 Apr 2012 14:32:43 +0200
Subject: [PATCH 509/509] Allow controlling volume with PulseAudio backend
Signed-off-by: Marc-Andr? Lureau <marcandre.lureau@redhat.com>
Signed-off-by: malc <av1474@comtv.ru>
---
audio/paaudio.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 94 insertions(+), 5 deletions(-)
diff --git a/audio/paaudio.c b/audio/paaudio.c
index 6f50c1c..e6708d0 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -677,15 +677,103 @@ static void qpa_fini_in (HWVoiceIn *hw)
static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
- (void) hw;
- (void) cmd;
+ PAVoiceOut *pa = (PAVoiceOut *) hw;
+ pa_operation *op;
+ pa_cvolume v;
+ paaudio *g = &glob_paaudio;
+
+ pa_cvolume_init (&v);
+
+ switch (cmd) {
+ case VOICE_VOLUME:
+ {
+ SWVoiceOut *sw;
+ va_list ap;
+
+ va_start (ap, cmd);
+ sw = va_arg (ap, SWVoiceOut *);
+ va_end (ap);
+
+ v.channels = 2;
+ v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX;
+ v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX;
+
+ pa_threaded_mainloop_lock (g->mainloop);
+
+ op = pa_context_set_sink_input_volume (g->context,
+ pa_stream_get_index (pa->stream),
+ &v, NULL, NULL);
+ if (!op)
+ qpa_logerr (pa_context_errno (g->context),
+ "set_sink_input_volume() failed\n");
+ else
+ pa_operation_unref (op);
+
+ op = pa_context_set_sink_input_mute (g->context,
+ pa_stream_get_index (pa->stream),
+ sw->vol.mute, NULL, NULL);
+ if (!op) {
+ qpa_logerr (pa_context_errno (g->context),
+ "set_sink_input_mute() failed\n");
+ } else {
+ pa_operation_unref (op);
+ }
+
+ pa_threaded_mainloop_unlock (g->mainloop);
+ }
+ }
return 0;
}
static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...)
{
- (void) hw;
- (void) cmd;
+ PAVoiceIn *pa = (PAVoiceIn *) hw;
+ pa_operation *op;
+ pa_cvolume v;
+ paaudio *g = &glob_paaudio;
+
+ pa_cvolume_init (&v);
+
+ switch (cmd) {
+ case VOICE_VOLUME:
+ {
+ SWVoiceIn *sw;
+ va_list ap;
+
+ va_start (ap, cmd);
+ sw = va_arg (ap, SWVoiceIn *);
+ va_end (ap);
+
+ v.channels = 2;
+ v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX;
+ v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX;
+
+ pa_threaded_mainloop_lock (g->mainloop);
+
+ /* FIXME: use the upcoming "set_source_output_{volume,mute}" */
+ op = pa_context_set_source_volume_by_index (g->context,
+ pa_stream_get_device_index (pa->stream),
+ &v, NULL, NULL);
+ if (!op) {
+ qpa_logerr (pa_context_errno (g->context),
+ "set_source_volume() failed\n");
+ } else {
+ pa_operation_unref(op);
+ }
+
+ op = pa_context_set_source_mute_by_index (g->context,
+ pa_stream_get_index (pa->stream),
+ sw->vol.mute, NULL, NULL);
+ if (!op) {
+ qpa_logerr (pa_context_errno (g->context),
+ "set_source_mute() failed\n");
+ } else {
+ pa_operation_unref (op);
+ }
+
+ pa_threaded_mainloop_unlock (g->mainloop);
+ }
+ }
return 0;
}
@@ -822,5 +910,6 @@ struct audio_driver pa_audio_driver = {
.max_voices_out = INT_MAX,
.max_voices_in = INT_MAX,
.voice_size_out = sizeof (PAVoiceOut),
- .voice_size_in = sizeof (PAVoiceIn)
+ .voice_size_in = sizeof (PAVoiceIn),
+ .ctl_caps = VOICE_VOLUME_CAP
};
--
1.7.10

105
qemu.spec
View File

@ -38,7 +38,7 @@
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 1.0
Release: 14%{?dist}
Release: 15%{?dist}
# Epoch because we pushed a qemu-1.0 package
Epoch: 2
License: GPLv2+ and LGPLv2+ and BSD
@ -104,7 +104,7 @@ Patch25: 0025-rbd-always-set-out-parameter-in-qemu_rbd_snap_list.patch
Patch26: 0026-e1000-bounds-packet-size-against-buffer-size.patch
Patch27: virtio-blk_refuse_SG_IO_requests_with_scsi_off.patch
# USB Redirect patches should go upstream soon!
# USB-redir patches all upstream for 1.1 except for the chardev flowcontrol set
Patch101: 0101-usb-redir-Clear-iso-irq-error-when-stopping-the-stre.patch
Patch102: 0102-usb-redir-Dynamically-adjust-iso-buffering-size-base.patch
Patch103: 0103-usb-redir-Pre-fill-our-isoc-input-buffer-before-send.patch
@ -151,6 +151,7 @@ Patch143: 0143-usb-redir-Notify-our-peer-when-we-reject-a-device-du.patch
Patch144: 0144-usb-redir-An-interface-count-of-0-is-a-valid-value.patch
Patch145: 0145-usb-redir-Reset-device-address-and-speed-on-disconne.patch
Patch146: 0146-usb-redir-Not-finding-an-async-urb-id-is-not-an-erro.patch
Patch147: 0147-usb-ehci-Ensure-frindex-writes-leave-a-valid-frindex.patch
# General bug fixes
Patch201: Fix_save-restore_of_in-kernel_i8259.patch
@ -160,6 +161,53 @@ Patch202: qemu-virtio-9p-noatime.patch
Patch301: enable_architectural_PMU_cpuid_leaf.patch
Patch302: qemu_virtio-scsi_support.patch
# QXL fixes backports, all are upstream for 1.1
Patch401: 0401-qxl-Slot-sanity-check-in-qxl_phys2virt-is-off-by-one.patch
Patch402: 0402-input-send-kbd-mouse-events-only-to-running-guests.patch
Patch403: 0403-qxl-fix-warnings-on-32bit.patch
Patch404: 0404-qxl-don-t-render-stuff-when-the-vm-is-stopped.patch
Patch405: 0405-qxl-set-only-off-screen-surfaces-dirty-instead-of-th.patch
Patch406: 0406-qxl-make-sure-primary-surface-is-saved-on-migration-.patch
Patch407: 0407-Add-SPICE-support-to-add_client-monitor-command.patch
Patch408: 0408-spice-support-ipv6-channel-address-in-monitor-events.patch
Patch409: 0409-qxl-drop-vram-bar-minimum-size.patch
Patch410: 0410-qxl-move-ram-size-init-to-new-function.patch
Patch411: 0411-qxl-add-user-friendly-bar-size-properties.patch
Patch412: 0412-qxl-fix-spice-sdl-no-cursor-regression.patch
Patch413: 0413-sdl-remove-NULL-check-g_malloc0-can-t-fail.patch
Patch414: 0414-qxl-drop-qxl_spice_update_area_async-definition.patch
Patch415: 0415-qxl-require-spice-0.8.2.patch
Patch416: 0416-qxl-remove-flipped.patch
Patch417: 0417-qxl-introduce-QXLCookie.patch
Patch418: 0418-qxl-make-qxl_render_update-async.patch
Patch419: 0419-spice-use-error_report-to-report-errors.patch
Patch420: 0420-Error-out-when-tls-channel-option-is-used-without-TL.patch
Patch421: 0421-qxl-properly-handle-upright-and-non-shared-surfaces.patch
Patch422: 0422-spice-set-spice-uuid-and-name.patch
Patch423: 0423-monitor-fix-client_migrate_info-error-handling.patch
Patch424: 0424-qxl-init_pipe_signaling-exit-on-failure.patch
Patch425: 0425-qxl-switch-qxl.c-to-trace-events.patch
Patch426: 0426-qxl-qxl_render.c-add-trace-events.patch
Patch427: 0427-hw-qxl.c-Fix-compilation-failures-on-32-bit-hosts.patch
Patch428: 0428-spice-fix-broken-initialization.patch
Patch429: 0429-ui-spice-display.c-Fix-compilation-warnings-on-32-bi.patch
Patch430: 0430-ui-spice-display-use-uintptr_t-when-casting-qxl-phys.patch
Patch431: 0431-qxl-add-optinal-64bit-vram-bar.patch
Patch432: 0432-qxl-set-default-values-of-vram-_size_mb-to-1.patch
Patch433: 0433-qxl-render-fix-broken-vnc-spice-since-commit-f934493.patch
Patch434: 0434-qxl-don-t-assert-on-guest-create_guest_primary.patch
# Spice volume control backports, all are upstream for 1.1
Patch501: 0501-audio-add-VOICE_VOLUME-ctl.patch
Patch502: 0502-audio-don-t-apply-volume-effect-if-backend-has-VOICE.patch
Patch503: 0503-hw-ac97-remove-USE_MIXER-code.patch
Patch504: 0504-hw-ac97-the-volume-mask-is-not-only-0x1f.patch
Patch505: 0505-hw-ac97-add-support-for-volume-control.patch
Patch506: 0506-audio-spice-add-support-for-volume-control.patch
Patch507: 0507-Do-not-use-pa_simple-PulseAudio-API.patch
Patch508: 0508-configure-pa_simple-is-not-needed-anymore.patch
Patch509: 0509-Allow-controlling-volume-with-PulseAudio-backend.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: SDL-devel zlib-devel which texi2html gnutls-devel cyrus-sasl-devel
BuildRequires: libaio-devel
@ -478,6 +526,7 @@ such as kvm_stat.
%patch144 -p1
%patch145 -p1
%patch146 -p1
%patch147 -p1
%patch201 -p1
%patch202 -p1
@ -485,6 +534,52 @@ such as kvm_stat.
%patch301 -p1
%patch302 -p1
%patch401 -p1
%patch402 -p1
%patch403 -p1
%patch404 -p1
%patch405 -p1
%patch406 -p1
%patch407 -p1
%patch408 -p1
%patch409 -p1
%patch410 -p1
%patch411 -p1
%patch412 -p1
%patch413 -p1
%patch414 -p1
%patch415 -p1
%patch416 -p1
%patch417 -p1
%patch418 -p1
%patch419 -p1
%patch420 -p1
%patch421 -p1
%patch422 -p1
%patch423 -p1
%patch424 -p1
%patch425 -p1
%patch426 -p1
%patch427 -p1
%patch428 -p1
%patch429 -p1
%patch430 -p1
%patch431 -p1
%patch432 -p1
%patch433 -p1
%patch434 -p1
%patch501 -p1
%patch502 -p1
%patch503 -p1
%patch504 -p1
%patch505 -p1
%patch506 -p1
%patch507 -p1
%patch508 -p1
%patch509 -p1
%build
# By default we build everything, but allow x86 to build a minimal version
# with only similar arch target support
@ -524,6 +619,7 @@ sed -i.debug 's/"-g $CFLAGS"/"$CFLAGS"/g' configure
--extra-ldflags="$extraldflags -pie -Wl,-z,relro -Wl,-z,now" \
--extra-cflags="%{optflags} -fPIE -DPIE" \
--enable-spice \
--enable-mixemu \
%if %{without rbd}
--disable-rbd \
%endif
@ -561,6 +657,7 @@ make clean
--disable-xen \
%ifarch %{ix86} x86_64
--enable-spice \
--enable-mixemu \
%endif
%if %{without rbd}
--disable-rbd \
@ -912,6 +1009,10 @@ fi
%{_mandir}/man1/qemu-img.1*
%changelog
* Thu Apr 19 2012 Hans de Goede <hdegoede@redhat.com> - 2:1.0-15
- Add a couple of backported QXL/Spice bugfixes
- Add spice volume control patches
* Fri Apr 6 2012 Paolo Bonzini <pbonzini@redhat.com> - 2:1.0-12
- Add back PPC and SPARC user emulators
- Update binfmt rules from upstream