#include <zlib.h>
#include "qapi/error.h"
-#include "qemu-common.h"
#include "qemu/timer.h"
#include "qemu/queue.h"
#include "qemu/atomic.h"
+#include "qemu/main-loop.h"
+#include "qemu/module.h"
#include "sysemu/sysemu.h"
#include "migration/blocker.h"
+#include "migration/vmstate.h"
#include "trace.h"
#include "qxl.h"
-/*
- * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as
- * such can be changed by the guest, so to avoid a guest trigerrable
- * abort we just qxl_set_guest_bug and set the return to NULL. Still
- * it may happen as a result of emulator bug as well.
- */
-#undef SPICE_RING_PROD_ITEM
-#define SPICE_RING_PROD_ITEM(qxl, r, ret) { \
- uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \
- if (prod >= ARRAY_SIZE((r)->items)) { \
- qxl_set_guest_bug(qxl, "SPICE_RING_PROD_ITEM indices mismatch " \
- "%u >= %zu", prod, ARRAY_SIZE((r)->items)); \
- ret = NULL; \
- } else { \
- ret = &(r)->items[prod].el; \
- } \
- }
-
#undef SPICE_RING_CONS_ITEM
#define SPICE_RING_CONS_ITEM(qxl, r, ret) { \
uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \
QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
0));
} else {
-#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
+/* >= release 0.12.6, < release 0.14.2 */
+#if SPICE_SERVER_VERSION >= 0x000c06 && SPICE_SERVER_VERSION < 0x000e02
if (qxl->max_outputs) {
spice_qxl_set_max_monitors(&qxl->ssd.qxl, qxl->max_outputs);
}
static void init_qxl_ram(PCIQXLDevice *d)
{
uint8_t *buf;
- uint64_t *item;
+ uint32_t prod;
+ QXLReleaseRing *ring;
buf = d->vga.vram_ptr;
d->ram = (QXLRam *)(buf + le32_to_cpu(d->shadow_rom.ram_header_offset));
SPICE_RING_INIT(&d->ram->cmd_ring);
SPICE_RING_INIT(&d->ram->cursor_ring);
SPICE_RING_INIT(&d->ram->release_ring);
- SPICE_RING_PROD_ITEM(d, &d->ram->release_ring, item);
- assert(item);
- *item = 0;
+
+ ring = &d->ram->release_ring;
+ prod = ring->prod & SPICE_RING_INDEX_MASK(ring);
+ assert(prod < ARRAY_SIZE(ring->items));
+ ring->items[prod].el = 0;
+
qxl_ring_set_dirty(d);
}
static inline void qxl_push_free_res(PCIQXLDevice *d, int flush)
{
QXLReleaseRing *ring = &d->ram->release_ring;
- uint64_t *item;
+ uint32_t prod;
int notify;
#define QXL_FREE_BUNCH_SIZE 32
if (notify) {
qxl_send_events(d, QXL_INTERRUPT_DISPLAY);
}
- SPICE_RING_PROD_ITEM(d, ring, item);
- if (!item) {
+
+ ring = &d->ram->release_ring;
+ prod = ring->prod & SPICE_RING_INDEX_MASK(ring);
+ if (prod >= ARRAY_SIZE(ring->items)) {
+ qxl_set_guest_bug(d, "SPICE_RING_PROD_ITEM indices mismatch "
+ "%u >= %zu", prod, ARRAY_SIZE(ring->items));
return;
}
- *item = 0;
+ ring->items[prod].el = 0;
d->num_free_res = 0;
d->last_release = NULL;
qxl_ring_set_dirty(d);
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
QXLReleaseRing *ring;
- uint64_t *item, id;
+ uint32_t prod;
+ uint64_t id;
+ if (!ext.info) {
+ return;
+ }
if (ext.group_id == MEMSLOT_GROUP_HOST) {
/* host group -> vga mode update request */
QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id);
* pci bar 0, $command.release_info
*/
ring = &qxl->ram->release_ring;
- SPICE_RING_PROD_ITEM(qxl, ring, item);
- if (!item) {
+ prod = ring->prod & SPICE_RING_INDEX_MASK(ring);
+ if (prod >= ARRAY_SIZE(ring->items)) {
+ qxl_set_guest_bug(qxl, "SPICE_RING_PROD_ITEM indices mismatch "
+ "%u >= %zu", prod, ARRAY_SIZE(ring->items));
return;
}
- if (*item == 0) {
+ if (ring->items[prod].el == 0) {
/* stick head into the ring */
id = ext.info->id;
ext.info->next = 0;
qxl_ram_set_dirty(qxl, &ext.info->next);
- *item = id;
+ ring->items[prod].el = id;
qxl_ring_set_dirty(qxl);
} else {
/* append item to the list */
return;
}
trace_qxl_enter_vga_mode(d->id);
-#if SPICE_SERVER_VERSION >= 0x000c03 /* release 0.12.3 */
spice_qxl_driver_unload(&d->ssd.qxl);
-#endif
graphic_console_set_hwops(d->ssd.dcl.con, d->vga.hw_ops, &d->vga);
update_displaychangelistener(&d->ssd.dcl, GUI_REFRESH_INTERVAL_DEFAULT);
qemu_spice_create_host_primary(&d->ssd);
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_clock_get_ns(QEMU_CLOCK_VIRTUAL), d->ram->log_buf);
+ if (TRACE_QXL_IO_LOG_ENABLED || d->guestdebug) {
+ /* We cannot trust the guest to NUL terminate d->ram->log_buf */
+ char *log_buf = g_strndup((const char *)d->ram->log_buf,
+ sizeof(d->ram->log_buf));
+ trace_qxl_io_log(d->id, log_buf);
+ if (d->guestdebug) {
+ fprintf(stderr, "qxl/guest-%d: %" PRId64 ": %s", d->id,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), log_buf);
+ }
+ g_free(log_buf);
}
break;
case QXL_IO_RESET:
SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
return;
}
+
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
+ char device_address[256] = "";
+ if (qemu_spice_fill_device_address(qxl->vga.con, device_address, 256)) {
+ spice_qxl_set_device_info(&qxl->ssd.qxl,
+ device_address,
+ 0,
+ qxl->max_outputs);
+ }
+#endif
+
qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);