aboutsummaryrefslogtreecommitdiff
path: root/hw/qxl.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/qxl.c')
-rw-r--r--hw/qxl.c109
1 files changed, 78 insertions, 31 deletions
diff --git a/hw/qxl.c b/hw/qxl.c
index ac69125f27..87ad49ad8b 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -625,7 +625,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;
}
@@ -748,7 +748,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);
@@ -1006,7 +1007,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);
@@ -1015,7 +1016,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);
@@ -1465,6 +1466,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 && qxl->mode != QXL_MODE_COMPAT) {
+ 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)
{
@@ -1478,14 +1519,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);
}
}
@@ -1518,6 +1554,31 @@ 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->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;
+ }
+ 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;
@@ -1556,13 +1617,6 @@ 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->revision == 1) {
- qxl->vram_size = 4096;
- }
- qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
memory_region_init_ram(&qxl->vram_bar, "qxl.vram", qxl->vram_size);
vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev);
@@ -1605,15 +1659,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);
@@ -1632,14 +1682,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.vgavram", qxl->vga.vram_size);
vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev);
qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
@@ -1821,6 +1866,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(),
};