From 366ba84f40f9b5b4b9ed05ea469a4a9ef419f96c Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Tue, 21 Feb 2012 11:31:45 +0100 Subject: [PATCH 3/4] qxl: set only off-screen surfaces dirty instead of the whole vram RH-Author: Yonit Halperin Message-id: <1329823906-8716-2-git-send-email-yhalperi@redhat.com> Patchwork-id: 37449 O-Subject: [RHEL 6.3 qemu-kvm PACTH 1/2] qxl: set only off-screen surfaces dirty instead of the whole vram Bugzilla: 790083 RH-Acked-by: Alon Levy RH-Acked-by: Hans de Goede RH-Acked-by: Uri Lublin We used to assure the guest surfaces were saved before migration by setting the whole vram dirty. This patch sets dirty only the areas that are actually used in the vram. upstream: http://patchwork.ozlabs.org/patch/141279/ Signed-off-by: Yonit Halperin --- hw/qxl.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 51 insertions(+), 10 deletions(-) Signed-off-by: Michal Novotny --- hw/qxl.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 51 insertions(+), 10 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 3d9ddd7..cdb2a3c 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1013,7 +1013,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d) qxl_spice_destroy_surfaces(d, QXL_SYNC); } -/* called from spice server thread context only */ +/* can be called also from spice server thread context */ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id) { uint64_t phys = le64_to_cpu(pqxl); @@ -1504,6 +1504,53 @@ static void qxl_hw_text_update(void *opaque, console_ch_t *chardata) } } +static void qxl_dirty_surfaces(PCIQXLDevice *qxl) +{ + ram_addr_t surface0_addr; + int i; + intptr_t vram_base; + ram_addr_t vram_addr; + + if (qxl->mode != QXL_MODE_NATIVE) { + return; + } + surface0_addr = qxl->vga.vram_offset + qxl->shadow_rom.draw_area_offset; + /* dirty the primary surface */ + qxl_set_dirty(surface0_addr, surface0_addr + qxl->shadow_rom.surface0_area_size); + + vram_addr = qxl->vram_offset; + vram_base = (intptr_t)qemu_get_ram_ptr(qxl->vram_offset); + + /* dirty the off-screen surfaces */ + for (i = 0; i < NUM_SURFACES; i++) { + QXLSurfaceCmd *cmd; + intptr_t surface_addr, 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_addr = (intptr_t)qxl_phys2virt(qxl, + cmd->u.surface_create.data, + MEMSLOT_GROUP_GUEST); + surface_size = cmd->u.surface_create.height * + abs(cmd->u.surface_create.stride); + surface_offset = surface_addr - vram_base; + surface_offset &= TARGET_PAGE_MASK; + + dprint(qxl, 3, "%s: dirty surface %d, addr1 %p, offset %p, size %d\n", + __func__, i, (void *)surface_addr, (void *)surface_offset, + surface_size); + qxl_set_dirty(vram_addr + surface_offset, + vram_addr + surface_offset + surface_size); + + } +} + static void qxl_vm_change_state_handler(void *opaque, int running, RunState state) { @@ -1517,15 +1564,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 */ - ram_addr_t vram_addr = qxl->vram_offset; - ram_addr_t surface0_addr = qxl->vga.vram_offset + qxl->shadow_rom.draw_area_offset; - qxl_set_dirty(vram_addr, vram_addr + qxl->vram_size); - qxl_set_dirty(surface0_addr, surface0_addr + qxl->shadow_rom.surface0_area_size); + } else { + /* make sure surfaces are saved before migration */ + qxl_dirty_surfaces(qxl); } } -- 1.7.7.6