Skip to content

Commit

Permalink
Merge remote-tracking branch 'spice/spice.v60' into staging
Browse files Browse the repository at this point in the history
* spice/spice.v60:
  hw/qxl: support client monitor configuration via device
  qxl: add trace-event for QXL_IO_LOG
  hw/qxl: tracing fixes
  qxl: better cleanup for surface destroy
  qxl: Ignore set_client_capabilities pre/post migrate
  qxl: dont update invalid area
  spice: send updates only for changed screen content
  spice: add screen mirror
  spice: split qemu_spice_create_update
  spice: switch to queue for vga mode updates
  • Loading branch information
Anthony Liguori committed Sep 17, 2012
2 parents de71bd6 + a639ab0 commit cd6dcc7
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 40 deletions.
7 changes: 7 additions & 0 deletions configure
Expand Up @@ -2738,6 +2738,9 @@ EOF
if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then
spice_qxl_io_monitors_config_async="yes"
fi
if $pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1; then
spice_qxl_client_monitors_config="yes"
fi
else
if test "$spice" = "yes" ; then
feature_not_found "spice"
Expand Down Expand Up @@ -3485,6 +3488,10 @@ if test "$spice_qxl_io_monitors_config_async" = "yes" ; then
echo "CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC=y" >> $config_host_mak
fi

if test "$spice_qxl_client_monitors_config" = "yes" ; then
echo "CONFIG_QXL_CLIENT_MONITORS_CONFIG=y" >> $config_host_mak
fi

if test "$smartcard" = "yes" ; then
echo "CONFIG_SMARTCARD=y" >> $config_host_mak
fi
Expand Down
107 changes: 101 additions & 6 deletions hw/qxl.c
Expand Up @@ -18,6 +18,8 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/

#include <zlib.h>

#include "qemu-common.h"
#include "qemu-timer.h"
#include "qemu-queue.h"
Expand Down Expand Up @@ -141,6 +143,7 @@ static void qxl_ring_set_dirty(PCIQXLDevice *qxl);

void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...)
{
trace_qxl_set_guest_bug(qxl->id);
qxl_send_events(qxl, QXL_INTERRUPT_ERROR);
qxl->guest_bug = 1;
if (qxl->guestdebug) {
Expand Down Expand Up @@ -201,6 +204,7 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uintptr_t)cookie);
} else {
qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
qxl_spice_destroy_surface_wait_complete(qxl, id);
}
}

Expand Down Expand Up @@ -597,9 +601,9 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
case QXL_MODE_VGA:
ret = false;
qemu_mutex_lock(&qxl->ssd.lock);
if (qxl->ssd.update != NULL) {
update = qxl->ssd.update;
qxl->ssd.update = NULL;
update = QTAILQ_FIRST(&qxl->ssd.updates);
if (update != NULL) {
QTAILQ_REMOVE(&qxl->ssd.updates, update, next);
*ext = update->ext;
ret = true;
}
Expand Down Expand Up @@ -953,6 +957,11 @@ static void interface_set_client_capabilities(QXLInstance *sin,
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);

if (runstate_check(RUN_STATE_INMIGRATE) ||
runstate_check(RUN_STATE_POSTMIGRATE)) {
return;
}

qxl->shadow_rom.client_present = client_present;
memcpy(qxl->shadow_rom.client_capabilities, caps, sizeof(caps));
qxl->rom->client_present = client_present;
Expand All @@ -964,6 +973,79 @@ static void interface_set_client_capabilities(QXLInstance *sin,

#endif

#if defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG) \
&& SPICE_SERVER_VERSION >= 0x000b05

static uint32_t qxl_crc32(const uint8_t *p, unsigned len)
{
/*
* zlib xors the seed with 0xffffffff, and xors the result
* again with 0xffffffff; Both are not done with linux's crc32,
* which we want to be compatible with, so undo that.
*/
return crc32(0xffffffff, p, len) ^ 0xffffffff;
}

/* called from main context only */
static int interface_client_monitors_config(QXLInstance *sin,
VDAgentMonitorsConfig *monitors_config)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);
int i;

/*
* Older windows drivers set int_mask to 0 when their ISR is called,
* then later set it to ~0. So it doesn't relate to the actual interrupts
* handled. However, they are old, so clearly they don't support this
* interrupt
*/
if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 ||
!(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) {
trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id,
qxl->ram->int_mask,
monitors_config);
return 0;
}
if (!monitors_config) {
return 1;
}
memset(&rom->client_monitors_config, 0,
sizeof(rom->client_monitors_config));
rom->client_monitors_config.count = monitors_config->num_of_monitors;
/* monitors_config->flags ignored */
if (rom->client_monitors_config.count >=
ARRAY_SIZE(rom->client_monitors_config.heads)) {
trace_qxl_client_monitors_config_capped(qxl->id,
monitors_config->num_of_monitors,
ARRAY_SIZE(rom->client_monitors_config.heads));
rom->client_monitors_config.count =
ARRAY_SIZE(rom->client_monitors_config.heads);
}
for (i = 0 ; i < rom->client_monitors_config.count ; ++i) {
VDAgentMonConfig *monitor = &monitors_config->monitors[i];
QXLURect *rect = &rom->client_monitors_config.heads[i];
/* monitor->depth ignored */
rect->left = monitor->x;
rect->top = monitor->y;
rect->right = monitor->x + monitor->width;
rect->bottom = monitor->y + monitor->height;
}
rom->client_monitors_config_crc = qxl_crc32(
(const uint8_t *)&rom->client_monitors_config,
sizeof(rom->client_monitors_config));
trace_qxl_client_monitors_config_crc(qxl->id,
sizeof(rom->client_monitors_config),
rom->client_monitors_config_crc);

trace_qxl_interrupt_client_monitors_config(qxl->id,
rom->client_monitors_config.count,
rom->client_monitors_config.heads);
qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);
return 1;
}
#endif

static const QXLInterface qxl_interface = {
.base.type = SPICE_INTERFACE_QXL,
.base.description = "qxl gpu",
Expand All @@ -988,6 +1070,10 @@ static const QXLInterface qxl_interface = {
#if SPICE_SERVER_VERSION >= 0x000b04
.set_client_capabilities = interface_set_client_capabilities,
#endif
#if SPICE_SERVER_VERSION >= 0x000b05 && \
defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG)
.client_monitors_config = interface_client_monitors_config,
#endif
};

static void qxl_enter_vga_mode(PCIQXLDevice *d)
Expand Down Expand Up @@ -1402,7 +1488,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
break;
}
trace_qxl_io_unexpected_vga_mode(d->id,
io_port, io_port_to_string(io_port));
addr, val, io_port_to_string(io_port));
/* be nice to buggy guest drivers */
if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
io_port < QXL_IO_RANGE_SIZE) {
Expand Down Expand Up @@ -1470,6 +1556,13 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
return;
}

if (update.left < 0 || update.top < 0 || update.left >= update.right ||
update.top >= update.bottom) {
qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: "
"invalid area(%d,%d,%d,%d)\n", update.left,
update.right, update.top, update.bottom);
break;
}
if (async == QXL_ASYNC) {
cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
QXL_IO_UPDATE_AREA_ASYNC);
Expand Down Expand Up @@ -1501,6 +1594,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
qxl_set_mode(d, val, 0);
break;
case QXL_IO_LOG:
trace_qxl_io_log(d->id, d->ram->log_buf);
if (d->guestdebug) {
fprintf(stderr, "qxl/guest-%d: %" PRId64 ": %s", d->id,
qemu_get_clock_ns(vm_clock), d->ram->log_buf);
Expand Down Expand Up @@ -1594,9 +1688,9 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
static uint64_t ioport_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
PCIQXLDevice *d = opaque;
PCIQXLDevice *qxl = opaque;

trace_qxl_io_read_unexpected(d->id);
trace_qxl_io_read_unexpected(qxl->id);
return 0xff;
}

Expand Down Expand Up @@ -1626,6 +1720,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
uint32_t old_pending;
uint32_t le_events = cpu_to_le32(events);

trace_qxl_send_events(d->id, events);
assert(qemu_spice_display_is_running(&d->ssd));
old_pending = __sync_fetch_and_or(&d->ram->int_pending, le_events);
if ((old_pending & le_events) == le_events) {
Expand Down
11 changes: 9 additions & 2 deletions trace-events
Expand Up @@ -932,8 +932,9 @@ qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) "%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_log(int qid, const uint8_t *log_buf) "%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_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char *desc) "%d 0x%"PRIx64"=%"PRIu64" (%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"
Expand Down Expand Up @@ -964,7 +965,7 @@ 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_monitors_config(int id) "%d"
qxl_spice_monitors_config(int qid) "%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"
Expand All @@ -973,6 +974,12 @@ 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_send_events(int qid, uint32_t events) "%d %d"
qxl_set_guest_bug(int qid) "%d"
qxl_interrupt_client_monitors_config(int qid, int num_heads, void *heads) "%d %d %p"
qxl_client_monitors_config_unsupported_by_guest(int qid, uint32_t int_mask, void *client_monitors_config) "%d %X %p"
qxl_client_monitors_config_capped(int qid, int requested, int limit) "%d %d %d"
qxl_client_monitors_config_crc(int qid, unsigned size, uint32_t crc32) "%d %u %u"

# hw/qxl-render.c
qxl_render_blit_guest_primary_initialized(void) ""
Expand Down

0 comments on commit cd6dcc7

Please sign in to comment.