]> git.proxmox.com Git - pve-qemu.git/blame - debian/patches/extra/0009-vga-make-display-updates-thread-safe.patch
bump version to 2.9.1-9
[pve-qemu.git] / debian / patches / extra / 0009-vga-make-display-updates-thread-safe.patch
CommitLineData
3dcc8d3b 1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
ddbcf45e
WB
2From: Gerd Hoffmann <kraxel@redhat.com>
3Date: Fri, 21 Apr 2017 11:16:27 +0200
3dcc8d3b 4Subject: [PATCH] vga: make display updates thread safe.
ddbcf45e
WB
5
6The vga code clears the dirty bits *after* reading the framebuffer
7memory. So if the guest framebuffer updates hits the race window
8between vga reading the framebuffer and vga clearing the dirty bits
9vga will miss that update
10
11Fix it by using the new memory_region_copy_and_clear_dirty()
12memory_region_copy_get_dirty() functions. That way we clear the
13dirty bitmap before reading the framebuffer. Any guest display
14updates happening in parallel will be properly tracked in the
15dirty bitmap then and the next display refresh will pick them up.
16
17Problem triggers with mttcg only. Before mttcg was merged tcg
18never ran in parallel to vga emulation. Using kvm will hide the
19problem too, due to qemu operating on a userspace copy of the
20kernel's dirty bitmap.
21
22Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
23Message-id: 20170421091632.30900-5-kraxel@redhat.com
24Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
25---
26 hw/display/vga.c | 36 +++++++++++++++++-------------------
27 1 file changed, 17 insertions(+), 19 deletions(-)
28
29diff --git a/hw/display/vga.c b/hw/display/vga.c
30index 3991b88aac..b2516c8d21 100644
31--- a/hw/display/vga.c
32+++ b/hw/display/vga.c
33@@ -1465,7 +1465,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
34 DisplaySurface *surface = qemu_console_surface(s->con);
35 int y1, y, update, linesize, y_start, double_scan, mask, depth;
36 int width, height, shift_control, line_offset, bwidth, bits;
37- ram_addr_t page0, page1, page_min, page_max;
38+ ram_addr_t page0, page1;
39+ DirtyBitmapSnapshot *snap = NULL;
40 int disp_width, multi_scan, multi_run;
41 uint8_t *d;
42 uint32_t v, addr1, addr;
43@@ -1480,9 +1481,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
44
45 full_update |= update_basic_params(s);
46
47- if (!full_update)
48- vga_sync_dirty_bitmap(s);
49-
50 s->get_resolution(s, &width, &height);
51 disp_width = width;
52
53@@ -1625,11 +1623,17 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
54 addr1 = (s->start_addr * 4);
55 bwidth = (width * bits + 7) / 8;
56 y_start = -1;
57- page_min = -1;
58- page_max = 0;
59 d = surface_data(surface);
60 linesize = surface_stride(surface);
61 y1 = 0;
62+
63+ if (!full_update) {
64+ vga_sync_dirty_bitmap(s);
65+ snap = memory_region_snapshot_and_clear_dirty(&s->vram, addr1,
66+ bwidth * height,
67+ DIRTY_MEMORY_VGA);
68+ }
69+
70 for(y = 0; y < height; y++) {
71 addr = addr1;
72 if (!(s->cr[VGA_CRTC_MODE] & 1)) {
73@@ -1644,17 +1648,17 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
74 update = full_update;
75 page0 = addr;
76 page1 = addr + bwidth - 1;
77- update |= memory_region_get_dirty(&s->vram, page0, page1 - page0,
78- DIRTY_MEMORY_VGA);
79+ if (full_update) {
80+ update = 1;
81+ } else {
82+ update = memory_region_snapshot_get_dirty(&s->vram, snap,
83+ page0, page1 - page0);
84+ }
85 /* explicit invalidation for the hardware cursor (cirrus only) */
86 update |= vga_scanline_invalidated(s, y);
87 if (update) {
88 if (y_start < 0)
89 y_start = y;
90- if (page0 < page_min)
91- page_min = page0;
92- if (page1 > page_max)
93- page_max = page1;
94 if (!(is_buffer_shared(surface))) {
95 vga_draw_line(s, d, s->vram_ptr + addr, width);
96 if (s->cursor_draw_line)
97@@ -1687,13 +1691,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
98 dpy_gfx_update(s->con, 0, y_start,
99 disp_width, y - y_start);
100 }
101- /* reset modified pages */
102- if (page_max >= page_min) {
103- memory_region_reset_dirty(&s->vram,
104- page_min,
105- page_max - page_min,
106- DIRTY_MEMORY_VGA);
107- }
108+ g_free(snap);
109 memset(s->invalidated_y_table, 0, sizeof(s->invalidated_y_table));
110 }
111
112--
1132.11.0
114