QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
0));
} else {
-/* >= release 0.12.6, < release 0.14.2 */
-#if SPICE_SERVER_VERSION >= 0x000c06 && SPICE_SERVER_VERSION < 0x000e02
+#if SPICE_SERVER_VERSION < 0x000e02 /* release 0.14.2 */
if (qxl->max_outputs) {
spice_qxl_set_max_monitors(&qxl->ssd.qxl, qxl->max_outputs);
}
qxl->guest_cursor = 0;
qemu_mutex_unlock(&qxl->track_lock);
if (qxl->ssd.cursor) {
- cursor_put(qxl->ssd.cursor);
+ cursor_unref(qxl->ssd.cursor);
}
qxl->ssd.cursor = cursor_builtin_hidden();
}
qxl_rom_set_dirty(qxl);
}
-#if SPICE_NEEDS_SET_MM_TIME
-static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
-{
- PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
-
- if (!qemu_spice_display_is_running(&qxl->ssd)) {
- return;
- }
-
- 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);
-}
-#endif
-
static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
return 1;
}
-#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
/* limit number of outputs based on setting limit */
if (qxl->max_outputs && qxl->max_outputs <= max_outputs) {
max_outputs = qxl->max_outputs;
}
-#endif
config_changed = qxl_rom_monitors_config_changed(rom,
monitors_config,
#endif
.set_compression_level = interface_set_compression_level,
-#if SPICE_NEEDS_SET_MM_TIME
- .set_mm_time = interface_set_mm_time,
-#endif
.get_init_info = interface_get_init_info,
/* the callbacks below are called from spice server thread context */
qxl_set_guest_bug(d, "%s: pci_region = %d", __func__, pci_region);
return 1;
}
+ assert(guest_end - pci_start <= memory_region_size(mr));
virt_start = (intptr_t)memory_region_get_ram_ptr(mr);
memslot.slot_id = slot_id;
/* can be also called from spice server thread context */
static bool qxl_get_check_slot_offset(PCIQXLDevice *qxl, QXLPHYSICAL pqxl,
- uint32_t *s, uint64_t *o)
+ uint32_t *s, uint64_t *o,
+ size_t size_requested)
{
uint64_t phys = le64_to_cpu(pqxl);
uint32_t slot = (phys >> (64 - 8)) & 0xff;
uint64_t offset = phys & 0xffffffffffff;
+ uint64_t size_available;
if (slot >= NUM_MEMSLOTS) {
qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot,
slot, offset, qxl->guest_slots[slot].size);
return false;
}
+ size_available = memory_region_size(qxl->guest_slots[slot].mr);
+ if (qxl->guest_slots[slot].offset + offset >= size_available) {
+ qxl_set_guest_bug(qxl,
+ "slot %d offset %"PRIu64" > region size %"PRIu64"\n",
+ slot, qxl->guest_slots[slot].offset + offset,
+ size_available);
+ return false;
+ }
+ size_available -= qxl->guest_slots[slot].offset + offset;
+ if (size_requested > size_available) {
+ qxl_set_guest_bug(qxl,
+ "slot %d offset %"PRIu64" size %zu: "
+ "overrun by %"PRIu64" bytes\n",
+ slot, offset, size_requested,
+ size_requested - size_available);
+ return false;
+ }
*s = slot;
*o = offset;
offset = le64_to_cpu(pqxl) & 0xffffffffffff;
return (void *)(intptr_t)offset;
case MEMSLOT_GROUP_GUEST:
- if (!qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset)) {
+ if (!qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset, size)) {
return NULL;
}
ptr = memory_region_get_ram_ptr(qxl->guest_slots[slot].mr);
}
}
-/* return 1 if surface destoy was initiated (in QXL_ASYNC case) or
+/* return 1 if surface destroy was initiated (in QXL_ASYNC case) or
* done (in QXL_SYNC case), 0 otherwise. */
static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
{
}
d->guest_slots[0].slot = slot;
- assert(qxl_add_memslot(d, 0, devmem, QXL_SYNC) == 0);
+ if (qxl_add_memslot(d, 0, devmem, QXL_SYNC) != 0) {
+ qxl_set_guest_bug(d, "device isn't initialized yet");
+ return;
+ }
d->guest_primary.surface = surface;
qxl_create_guest_primary(d, 0, QXL_SYNC);
uint32_t slot;
bool rc;
- rc = qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset);
- assert(rc == true);
size = (uint64_t)height * abs(stride);
+ rc = qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset, size);
+ assert(rc == true);
trace_qxl_surfaces_dirty(qxl->id, offset, size);
qxl_set_dirty(qxl->guest_slots[slot].mr,
qxl->guest_slots[slot].offset + offset,
qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
- qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
+ qxl->update_irq = qemu_bh_new_guarded(qxl_update_irq_bh, qxl,
+ &DEVICE(qxl)->mem_reentrancy_guard);
qxl_reset_state(qxl);
- qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl);
- qxl->ssd.cursor_bh = qemu_bh_new(qemu_spice_cursor_refresh_bh, &qxl->ssd);
+ qxl->update_area_bh = qemu_bh_new_guarded(qxl_render_update_area_bh, qxl,
+ &DEVICE(qxl)->mem_reentrancy_guard);
+ qxl->ssd.cursor_bh = qemu_bh_new_guarded(qemu_spice_cursor_refresh_bh, &qxl->ssd,
+ &DEVICE(qxl)->mem_reentrancy_guard);
}
static void qxl_realize_primary(PCIDevice *dev, Error **errp)
DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1),
DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 16),
DEFINE_PROP_INT32("surfaces", PCIQXLDevice, ssd.num_surfaces, 1024),
-#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
DEFINE_PROP_UINT16("max_outputs", PCIQXLDevice, max_outputs, 0),
-#endif
DEFINE_PROP_UINT32("xres", PCIQXLDevice, xres, 0),
DEFINE_PROP_UINT32("yres", PCIQXLDevice, yres, 0),
DEFINE_PROP_BOOL("global-vmstate", PCIQXLDevice, vga.global_vmstate, false),