34b321
From 13bf417cd4063f5db2f0a79265745481d4c69d0d Mon Sep 17 00:00:00 2001
34b321
From: Gerd Hoffmann <kraxel@redhat.com>
34b321
Date: Fri, 22 Jul 2016 09:34:40 +0200
34b321
Subject: [PATCH 3/4] qxl: fix surface migration
34b321
34b321
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
34b321
Message-id: <1469180081-28522-4-git-send-email-kraxel@redhat.com>
34b321
Patchwork-id: 71315
34b321
O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 3/4] qxl: fix surface migration
34b321
Bugzilla: 1355730
34b321
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
34b321
RH-Acked-by: John Snow <jsnow@redhat.com>
34b321
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
34b321
34b321
Create a helper function qxl_dirty_one_surface() to mark a single qxl
34b321
surface as dirty.  Use the new qxl_get_check_slot_offset function and
34b321
lookup the memory region from the slot instead of assuming the surface
34b321
is stored in vram.
34b321
34b321
Use the new helper function in qxl_dirty_surfaces, for both primary and
34b321
off-screen surfaces.  For off-screen surfaces this is no functional
34b321
change.  For primary surfaces this will dirty only the memory actually
34b321
used instead of the whole surface0 region.  It will also work correctly
34b321
in case the guest places the primary surface in vram instead of the
34b321
surface0 region (linux kms driver does that).
34b321
34b321
https://bugzilla.redhat.com/show_bug.cgi?id=1235732
34b321
34b321
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
34b321
Message-id: 1466597244-5938-3-git-send-email-kraxel@redhat.com
34b321
(cherry picked from commit 1331eab216c9dc4e50a48a34d14926b31a7fd611)
34b321
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
34b321
34b321
Conflicts:
34b321
	hw/display/trace-events
34b321
---
34b321
 hw/display/qxl.c | 37 +++++++++++++++++++++----------------
34b321
 trace-events     |  2 +-
34b321
 2 files changed, 22 insertions(+), 17 deletions(-)
34b321
34b321
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
34b321
index de5770e..d65c830 100644
34b321
--- a/hw/display/qxl.c
34b321
+++ b/hw/display/qxl.c
34b321
@@ -1822,9 +1822,23 @@ static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
34b321
     }
34b321
 }
34b321
 
34b321
+static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl,
34b321
+                                  uint32_t height, int32_t stride)
34b321
+{
34b321
+    uint64_t offset;
34b321
+    uint32_t slot, size;
34b321
+    bool rc;
34b321
+
34b321
+    rc = qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset);
34b321
+    assert(rc == true);
34b321
+    size = height * abs(stride);
34b321
+    trace_qxl_surfaces_dirty(qxl->id, (int)offset, size);
34b321
+    qxl_set_dirty(qxl->guest_slots[slot].mr,
34b321
+                  qxl->guest_slots[slot].offset + offset, size);
34b321
+}
34b321
+
34b321
 static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
34b321
 {
34b321
-    uintptr_t vram_start;
34b321
     int i;
34b321
 
34b321
     if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) {
34b321
@@ -1832,16 +1846,13 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
34b321
     }
34b321
 
34b321
     /* dirty the primary surface */
34b321
-    qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
34b321
-                  qxl->shadow_rom.surface0_area_size);
34b321
-
34b321
-    vram_start = (uintptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
34b321
+    qxl_dirty_one_surface(qxl, qxl->guest_primary.surface.mem,
34b321
+                          qxl->guest_primary.surface.height,
34b321
+                          qxl->guest_primary.surface.stride);
34b321
 
34b321
     /* dirty the off-screen surfaces */
34b321
     for (i = 0; i < qxl->ssd.num_surfaces; i++) {
34b321
         QXLSurfaceCmd *cmd;
34b321
-        intptr_t surface_offset;
34b321
-        int surface_size;
34b321
 
34b321
         if (qxl->guest_surfaces.cmds[i] == 0) {
34b321
             continue;
34b321
@@ -1851,15 +1862,9 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
34b321
                             MEMSLOT_GROUP_GUEST);
34b321
         assert(cmd);
34b321
         assert(cmd->type == QXL_SURFACE_CMD_CREATE);
34b321
-        surface_offset = (intptr_t)qxl_phys2virt(qxl,
34b321
-                                                 cmd->u.surface_create.data,
34b321
-                                                 MEMSLOT_GROUP_GUEST);
34b321
-        assert(surface_offset);
34b321
-        surface_offset -= vram_start;
34b321
-        surface_size = cmd->u.surface_create.height *
34b321
-                       abs(cmd->u.surface_create.stride);
34b321
-        trace_qxl_surfaces_dirty(qxl->id, i, (int)surface_offset, surface_size);
34b321
-        qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
34b321
+        qxl_dirty_one_surface(qxl, cmd->u.surface_create.data,
34b321
+                              cmd->u.surface_create.height,
34b321
+                              cmd->u.surface_create.stride);
34b321
     }
34b321
 }
34b321
 
34b321
diff --git a/trace-events b/trace-events
34b321
index b43132c..4da84b2 100644
34b321
--- a/trace-events
34b321
+++ b/trace-events
34b321
@@ -1078,7 +1078,7 @@ qxl_spice_reset_image_cache(int qid) "%d"
34b321
 qxl_spice_reset_memslots(int qid) "%d"
34b321
 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]"
34b321
 qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d"
34b321
-qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d"
34b321
+qxl_surfaces_dirty(int qid, int offset, int size) "%d offset=%d size=%d"
34b321
 qxl_send_events(int qid, uint32_t events) "%d %d"
34b321
 qxl_send_events_vm_stopped(int qid, uint32_t events) "%d %d"
34b321
 qxl_set_guest_bug(int qid) "%d"
34b321
-- 
34b321
1.8.3.1
34b321