From f06b85218a41fd6f8e797a925f4ea75640b69c9e Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Mon, 20 Jan 2014 12:44:19 +0200 Subject: [PATCH 1/4] qxl: clear irq on reset Without this we occasionally trigger an assert at hw/pci/pci.c:pcibus_reset that asserts the irq_count is zero on reset. This has become a problem with the new drm driver for linux, since doing a reboot from console causes a race between console updates that set the irq and the reset assertion that the irq is clear. Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/display/qxl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/display/qxl.c b/hw/display/qxl.c index e4f172e3fb..56b61c8ad8 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1126,6 +1126,7 @@ static void qxl_reset_state(PCIQXLDevice *d) d->num_free_res = 0; d->last_release = NULL; memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty)); + qxl_update_irq(d); } static void qxl_soft_reset(PCIQXLDevice *d) From 3761abb167847e9d848588bf15c5d7476845f7e8 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Mon, 20 Jan 2014 18:57:12 +0200 Subject: [PATCH 2/4] hw/display/qxl: fix signed to unsigned comparison Several small signedness / overflow corrections to qxl_create_guest_primary: 1. use 64 bit unsigned for size to avoid overflow possible from two 32 bit multiplicants. 2. correct sign for requested_height 3. add a more verbose error message when setting guest bug state (which causes a complete guess blackout until reset, so it helps if it is verbose). Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/display/qxl.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 56b61c8ad8..334c2719f8 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -19,6 +19,7 @@ */ #include +#include #include "qemu-common.h" #include "qemu/timer.h" @@ -1361,14 +1362,16 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm, { QXLDevSurfaceCreate surface; QXLSurfaceCreate *sc = &qxl->guest_primary.surface; - int size; - int requested_height = le32_to_cpu(sc->height); + uint32_t requested_height = le32_to_cpu(sc->height); int requested_stride = le32_to_cpu(sc->stride); - size = abs(requested_stride) * requested_height; - if (size > qxl->vgamem_size) { - qxl_set_guest_bug(qxl, "%s: requested primary larger then framebuffer" - " size", __func__); + if (requested_stride == INT32_MIN || + abs(requested_stride) * (uint64_t)requested_height + > qxl->vgamem_size) { + qxl_set_guest_bug(qxl, "%s: requested primary larger than framebuffer" + " stride %d x height %" PRIu32 " > %" PRIu32, + __func__, requested_stride, requested_height, + qxl->vgamem_size); return; } From 795ca114d353e02752a29f64902215bb30c58c21 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Thu, 2 Jan 2014 09:25:56 -0600 Subject: [PATCH 3/4] Add the ability to vary Spice playback and record rates, to facilitate Opus support. Signed-off-by: Jeremy White Signed-off-by: Gerd Hoffmann --- audio/spiceaudio.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 5af436c31d..fceee50adb 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -25,8 +25,17 @@ #include "audio.h" #include "audio_int.h" -#define LINE_IN_SAMPLES 1024 -#define LINE_OUT_SAMPLES 1024 +#if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3 +#define LINE_OUT_SAMPLES (480 * 4) +#else +#define LINE_OUT_SAMPLES (256 * 4) +#endif + +#if SPICE_INTERFACE_RECORD_MAJOR > 2 || SPICE_INTERFACE_RECORD_MINOR >= 3 +#define LINE_IN_SAMPLES (480 * 4) +#else +#define LINE_IN_SAMPLES (256 * 4) +#endif typedef struct SpiceRateCtl { int64_t start_ticks; @@ -111,7 +120,11 @@ static int line_out_init (HWVoiceOut *hw, struct audsettings *as) SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); struct audsettings settings; +#if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3 + settings.freq = spice_server_get_best_playback_rate(NULL); +#else settings.freq = SPICE_INTERFACE_PLAYBACK_FREQ; +#endif settings.nchannels = SPICE_INTERFACE_PLAYBACK_CHAN; settings.fmt = AUD_FMT_S16; settings.endianness = AUDIO_HOST_ENDIANNESS; @@ -122,6 +135,9 @@ static int line_out_init (HWVoiceOut *hw, struct audsettings *as) out->sin.base.sif = &playback_sif.base; qemu_spice_add_interface (&out->sin.base); +#if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3 + spice_server_set_playback_rate(&out->sin, settings.freq); +#endif return 0; } @@ -232,7 +248,11 @@ static int line_in_init (HWVoiceIn *hw, struct audsettings *as) SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); struct audsettings settings; +#if SPICE_INTERFACE_RECORD_MAJOR > 2 || SPICE_INTERFACE_RECORD_MINOR >= 3 + settings.freq = spice_server_get_best_record_rate(NULL); +#else settings.freq = SPICE_INTERFACE_RECORD_FREQ; +#endif settings.nchannels = SPICE_INTERFACE_RECORD_CHAN; settings.fmt = AUD_FMT_S16; settings.endianness = AUDIO_HOST_ENDIANNESS; @@ -243,6 +263,9 @@ static int line_in_init (HWVoiceIn *hw, struct audsettings *as) in->sin.base.sif = &record_sif.base; qemu_spice_add_interface (&in->sin.base); +#if SPICE_INTERFACE_RECORD_MAJOR > 2 || SPICE_INTERFACE_RECORD_MINOR >= 3 + spice_server_set_record_rate(&in->sin, settings.freq); +#endif return 0; } From 890911464934aebcb4409ad2495449d15d7347b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sat, 11 Jan 2014 00:20:24 +0100 Subject: [PATCH 4/4] spice: hook qemu_chr_fe_set_open() event to ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This wires up a spice port event on virtio-ports open/close, so the client is notified when the other end is ready. Signed-off-by: Marc-André Lureau Signed-off-by: Gerd Hoffmann --- spice-qemu-char.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/spice-qemu-char.c b/spice-qemu-char.c index 16439c5860..6624559952 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -212,7 +212,7 @@ static void spice_chr_close(struct CharDriverState *chr) g_free(s); } -static void spice_chr_set_fe_open(struct CharDriverState *chr, int fe_open) +static void spice_vmc_set_fe_open(struct CharDriverState *chr, int fe_open) { SpiceCharDriver *s = chr->opaque; if (fe_open) { @@ -222,6 +222,19 @@ static void spice_chr_set_fe_open(struct CharDriverState *chr, int fe_open) } } +static void spice_port_set_fe_open(struct CharDriverState *chr, int fe_open) +{ +#if SPICE_SERVER_VERSION >= 0x000c02 + SpiceCharDriver *s = chr->opaque; + + if (fe_open) { + spice_server_port_event(&s->sin, SPICE_PORT_EVENT_OPENED); + } else { + spice_server_port_event(&s->sin, SPICE_PORT_EVENT_CLOSED); + } +#endif +} + static void spice_chr_fe_event(struct CharDriverState *chr, int event) { #if SPICE_SERVER_VERSION >= 0x000c02 @@ -248,7 +261,9 @@ static void print_allowed_subtypes(void) fprintf(stderr, "\n"); } -static CharDriverState *chr_open(const char *subtype) +static CharDriverState *chr_open(const char *subtype, + void (*set_fe_open)(struct CharDriverState *, int)) + { CharDriverState *chr; SpiceCharDriver *s; @@ -262,7 +277,7 @@ static CharDriverState *chr_open(const char *subtype) chr->chr_write = spice_chr_write; chr->chr_add_watch = spice_chr_add_watch; chr->chr_close = spice_chr_close; - chr->chr_set_fe_open = spice_chr_set_fe_open; + chr->chr_set_fe_open = set_fe_open; chr->explicit_be_open = true; chr->chr_fe_event = spice_chr_fe_event; @@ -291,7 +306,7 @@ CharDriverState *qemu_chr_open_spice_vmc(const char *type) return NULL; } - return chr_open(type); + return chr_open(type, spice_vmc_set_fe_open); } #if SPICE_SERVER_VERSION >= 0x000c02 @@ -305,7 +320,7 @@ CharDriverState *qemu_chr_open_spice_port(const char *name) return NULL; } - chr = chr_open("port"); + chr = chr_open("port", spice_port_set_fe_open); s = chr->opaque; s->sin.portname = g_strdup(name);