From e65294157d4b69393b3f819c99f4f647452b48e3 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 28 Aug 2017 14:33:07 +0200 Subject: [PATCH 1/6] vga: fix display update region calculation (split screen) vga display update mis-calculated the region for the dirty bitmap snapshot in case split screen mode is used. This can trigger an assert in cpu_physical_memory_snapshot_get_dirty(). Impact: DoS for privileged guest users. Fixes: CVE-2017-13673 Fixes: fec5e8c92becad223df9d972770522f64aafdb72 Cc: P J P Reported-by: David Buchanan Signed-off-by: Gerd Hoffmann Message-id: 20170828123307.15392-1-kraxel@redhat.com --- hw/display/vga.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/display/vga.c b/hw/display/vga.c index 3433102ef3..ad7a46563c 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1628,9 +1628,15 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) y1 = 0; if (!full_update) { + ram_addr_t region_start = addr1; + ram_addr_t region_end = addr1 + line_offset * height; vga_sync_dirty_bitmap(s); - snap = memory_region_snapshot_and_clear_dirty(&s->vram, addr1, - line_offset * height, + if (s->line_compare < height) { + /* split screen mode */ + region_start = 0; + } + snap = memory_region_snapshot_and_clear_dirty(&s->vram, region_start, + region_end - region_start, DIRTY_MEMORY_VGA); } From 3d90c6254863693a6b13d918d2b8682e08bbc681 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 28 Aug 2017 14:29:06 +0200 Subject: [PATCH 2/6] vga: stop passing pointers to vga_draw_line* functions Instead pass around the address (aka offset into vga memory). Add vga_read_* helper functions which apply vbe_size_mask to the address, to make sure the address stays within the valid range, similar to the cirrus blitter fixes (commits ffaf857778 and 026aeffcb4). Impact: DoS for privileged guest users. qemu crashes with a segfault, when hitting the guard page after vga memory allocation, while reading vga memory for display updates. Fixes: CVE-2017-13672 Cc: P J P Reported-by: David Buchanan Signed-off-by: Gerd Hoffmann Message-id: 20170828122906.18993-1-kraxel@redhat.com --- hw/display/vga-helpers.h | 202 +++++++++++++++++++++------------------ hw/display/vga.c | 5 +- hw/display/vga_int.h | 1 + 3 files changed, 114 insertions(+), 94 deletions(-) diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h index 94f6de2046..5a752b3f9e 100644 --- a/hw/display/vga-helpers.h +++ b/hw/display/vga-helpers.h @@ -95,20 +95,46 @@ static void vga_draw_glyph9(uint8_t *d, int linesize, } while (--h); } +static inline uint8_t vga_read_byte(VGACommonState *vga, uint32_t addr) +{ + return vga->vram_ptr[addr & vga->vbe_size_mask]; +} + +static inline uint16_t vga_read_word_le(VGACommonState *vga, uint32_t addr) +{ + uint32_t offset = addr & vga->vbe_size_mask & ~1; + uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset); + return lduw_le_p(ptr); +} + +static inline uint16_t vga_read_word_be(VGACommonState *vga, uint32_t addr) +{ + uint32_t offset = addr & vga->vbe_size_mask & ~1; + uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset); + return lduw_be_p(ptr); +} + +static inline uint32_t vga_read_dword_le(VGACommonState *vga, uint32_t addr) +{ + uint32_t offset = addr & vga->vbe_size_mask & ~3; + uint32_t *ptr = (uint32_t *)(vga->vram_ptr + offset); + return ldl_le_p(ptr); +} + /* * 4 color mode */ -static void vga_draw_line2(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line2(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { uint32_t plane_mask, *palette, data, v; int x; - palette = s1->last_palette; - plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; + palette = vga->last_palette; + plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { - data = ((uint32_t *)s)[0]; + data = vga_read_dword_le(vga, addr); data &= plane_mask; v = expand2[GET_PLANE(data, 0)]; v |= expand2[GET_PLANE(data, 2)] << 2; @@ -124,7 +150,7 @@ static void vga_draw_line2(VGACommonState *s1, uint8_t *d, ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; d += 32; - s += 4; + addr += 4; } } @@ -134,17 +160,17 @@ static void vga_draw_line2(VGACommonState *s1, uint8_t *d, /* * 4 color mode, dup2 horizontal */ -static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { uint32_t plane_mask, *palette, data, v; int x; - palette = s1->last_palette; - plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; + palette = vga->last_palette; + plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { - data = ((uint32_t *)s)[0]; + data = vga_read_dword_le(vga, addr); data &= plane_mask; v = expand2[GET_PLANE(data, 0)]; v |= expand2[GET_PLANE(data, 2)] << 2; @@ -160,24 +186,24 @@ static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d, PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); d += 64; - s += 4; + addr += 4; } } /* * 16 color mode */ -static void vga_draw_line4(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line4(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { uint32_t plane_mask, data, v, *palette; int x; - palette = s1->last_palette; - plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; + palette = vga->last_palette; + plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { - data = ((uint32_t *)s)[0]; + data = vga_read_dword_le(vga, addr); data &= plane_mask; v = expand4[GET_PLANE(data, 0)]; v |= expand4[GET_PLANE(data, 1)] << 1; @@ -192,24 +218,24 @@ static void vga_draw_line4(VGACommonState *s1, uint8_t *d, ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; d += 32; - s += 4; + addr += 4; } } /* * 16 color mode, dup2 horizontal */ -static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { uint32_t plane_mask, data, v, *palette; int x; - palette = s1->last_palette; - plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; + palette = vga->last_palette; + plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { - data = ((uint32_t *)s)[0]; + data = vga_read_dword_le(vga, addr); data &= plane_mask; v = expand4[GET_PLANE(data, 0)]; v |= expand4[GET_PLANE(data, 1)] << 1; @@ -224,7 +250,7 @@ static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d, PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); d += 64; - s += 4; + addr += 4; } } @@ -233,21 +259,21 @@ static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d, * * XXX: add plane_mask support (never used in standard VGA modes) */ -static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { uint32_t *palette; int x; - palette = s1->last_palette; + palette = vga->last_palette; width >>= 3; for(x = 0; x < width; x++) { - PUT_PIXEL2(d, 0, palette[s[0]]); - PUT_PIXEL2(d, 1, palette[s[1]]); - PUT_PIXEL2(d, 2, palette[s[2]]); - PUT_PIXEL2(d, 3, palette[s[3]]); + PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]); + PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]); + PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]); + PUT_PIXEL2(d, 3, palette[vga_read_byte(vga, addr + 3)]); d += 32; - s += 4; + addr += 4; } } @@ -256,63 +282,63 @@ static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d, * * XXX: add plane_mask support (never used in standard VGA modes) */ -static void vga_draw_line8(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line8(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { uint32_t *palette; int x; - palette = s1->last_palette; + palette = vga->last_palette; width >>= 3; for(x = 0; x < width; x++) { - ((uint32_t *)d)[0] = palette[s[0]]; - ((uint32_t *)d)[1] = palette[s[1]]; - ((uint32_t *)d)[2] = palette[s[2]]; - ((uint32_t *)d)[3] = palette[s[3]]; - ((uint32_t *)d)[4] = palette[s[4]]; - ((uint32_t *)d)[5] = palette[s[5]]; - ((uint32_t *)d)[6] = palette[s[6]]; - ((uint32_t *)d)[7] = palette[s[7]]; + ((uint32_t *)d)[0] = palette[vga_read_byte(vga, addr + 0)]; + ((uint32_t *)d)[1] = palette[vga_read_byte(vga, addr + 1)]; + ((uint32_t *)d)[2] = palette[vga_read_byte(vga, addr + 2)]; + ((uint32_t *)d)[3] = palette[vga_read_byte(vga, addr + 3)]; + ((uint32_t *)d)[4] = palette[vga_read_byte(vga, addr + 4)]; + ((uint32_t *)d)[5] = palette[vga_read_byte(vga, addr + 5)]; + ((uint32_t *)d)[6] = palette[vga_read_byte(vga, addr + 6)]; + ((uint32_t *)d)[7] = palette[vga_read_byte(vga, addr + 7)]; d += 32; - s += 8; + addr += 8; } } /* * 15 bit color */ -static void vga_draw_line15_le(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line15_le(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { int w; uint32_t v, r, g, b; w = width; do { - v = lduw_le_p((void *)s); + v = vga_read_word_le(vga, addr); r = (v >> 7) & 0xf8; g = (v >> 2) & 0xf8; b = (v << 3) & 0xf8; ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 2; + addr += 2; d += 4; } while (--w != 0); } -static void vga_draw_line15_be(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line15_be(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { int w; uint32_t v, r, g, b; w = width; do { - v = lduw_be_p((void *)s); + v = vga_read_word_be(vga, addr); r = (v >> 7) & 0xf8; g = (v >> 2) & 0xf8; b = (v << 3) & 0xf8; ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 2; + addr += 2; d += 4; } while (--w != 0); } @@ -320,38 +346,38 @@ static void vga_draw_line15_be(VGACommonState *s1, uint8_t *d, /* * 16 bit color */ -static void vga_draw_line16_le(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line16_le(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { int w; uint32_t v, r, g, b; w = width; do { - v = lduw_le_p((void *)s); + v = vga_read_word_le(vga, addr); r = (v >> 8) & 0xf8; g = (v >> 3) & 0xfc; b = (v << 3) & 0xf8; ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 2; + addr += 2; d += 4; } while (--w != 0); } -static void vga_draw_line16_be(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line16_be(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { int w; uint32_t v, r, g, b; w = width; do { - v = lduw_be_p((void *)s); + v = vga_read_word_be(vga, addr); r = (v >> 8) & 0xf8; g = (v >> 3) & 0xfc; b = (v << 3) & 0xf8; ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 2; + addr += 2; d += 4; } while (--w != 0); } @@ -359,36 +385,36 @@ static void vga_draw_line16_be(VGACommonState *s1, uint8_t *d, /* * 24 bit color */ -static void vga_draw_line24_le(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line24_le(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { int w; uint32_t r, g, b; w = width; do { - b = s[0]; - g = s[1]; - r = s[2]; + b = vga_read_byte(vga, addr + 0); + g = vga_read_byte(vga, addr + 1); + r = vga_read_byte(vga, addr + 2); ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 3; + addr += 3; d += 4; } while (--w != 0); } -static void vga_draw_line24_be(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line24_be(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { int w; uint32_t r, g, b; w = width; do { - r = s[0]; - g = s[1]; - b = s[2]; + r = vga_read_byte(vga, addr + 0); + g = vga_read_byte(vga, addr + 1); + b = vga_read_byte(vga, addr + 2); ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 3; + addr += 3; d += 4; } while (--w != 0); } @@ -396,44 +422,36 @@ static void vga_draw_line24_be(VGACommonState *s1, uint8_t *d, /* * 32 bit color */ -static void vga_draw_line32_le(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line32_le(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { -#ifndef HOST_WORDS_BIGENDIAN - memcpy(d, s, width * 4); -#else int w; uint32_t r, g, b; w = width; do { - b = s[0]; - g = s[1]; - r = s[2]; + b = vga_read_byte(vga, addr + 0); + g = vga_read_byte(vga, addr + 1); + r = vga_read_byte(vga, addr + 2); ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 4; + addr += 4; d += 4; } while (--w != 0); -#endif } -static void vga_draw_line32_be(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width) +static void vga_draw_line32_be(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width) { -#ifdef HOST_WORDS_BIGENDIAN - memcpy(d, s, width * 4); -#else int w; uint32_t r, g, b; w = width; do { - r = s[1]; - g = s[2]; - b = s[3]; + r = vga_read_byte(vga, addr + 1); + g = vga_read_byte(vga, addr + 2); + b = vga_read_byte(vga, addr + 3); ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); - s += 4; + addr += 4; d += 4; } while (--w != 0); -#endif } diff --git a/hw/display/vga.c b/hw/display/vga.c index ad7a46563c..6fc8c8708a 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1005,7 +1005,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) } typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d, - const uint8_t *s, int width); + uint32_t srcaddr, int width); #include "vga-helpers.h" @@ -1666,7 +1666,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) if (y_start < 0) y_start = y; if (!(is_buffer_shared(surface))) { - vga_draw_line(s, d, s->vram_ptr + addr, width); + vga_draw_line(s, d, addr, width); if (s->cursor_draw_line) s->cursor_draw_line(s, d, y); } @@ -2170,6 +2170,7 @@ void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate) if (!s->vbe_size) { s->vbe_size = s->vram_size; } + s->vbe_size_mask = s->vbe_size - 1; s->is_vbe_vmstate = 1; memory_region_init_ram_nomigrate(&s->vram, obj, "vga.vram", s->vram_size, diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h index dd6c958da3..ad34a1f048 100644 --- a/hw/display/vga_int.h +++ b/hw/display/vga_int.h @@ -94,6 +94,7 @@ typedef struct VGACommonState { uint32_t vram_size; uint32_t vram_size_mb; /* property */ uint32_t vbe_size; + uint32_t vbe_size_mask; uint32_t latch; bool has_chain4_alias; MemoryRegion chain4_alias; From 79c5a10cdda1aed00d7ee4ef87de2ef8c854f4a5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 28 Aug 2017 14:39:32 +0200 Subject: [PATCH 3/6] qxl: drop mono cursor support The chunk size sanity check in qxl_render_cursor works for SPICE_CURSOR_TYPE_ALPHA cursors only. So support for SPICE_CURSOR_TYPE_MONO cursors must be broken for ages without anyone noticing. Most likely it simply isn't used any more by guest drivers. Drop the dead code. Signed-off-by: Gerd Hoffmann Message-id: 20170828123933.30323-2-kraxel@redhat.com --- hw/display/qxl-render.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c index 9ad9d9e0f5..e1b3f05ecb 100644 --- a/hw/display/qxl-render.c +++ b/hw/display/qxl-render.c @@ -207,7 +207,6 @@ void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie) static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor) { QEMUCursor *c; - uint8_t *image, *mask; size_t size; c = cursor_alloc(cursor->header.width, cursor->header.height); @@ -221,14 +220,6 @@ static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor) cursor_print_ascii_art(c, "qxl/alpha"); } break; - case SPICE_CURSOR_TYPE_MONO: - mask = cursor->chunk.data; - image = mask + cursor_get_mono_bpl(c) * c->width; - cursor_set_mono(c, 0xffffff, 0x000000, image, 1, mask); - if (qxl->debug > 2) { - cursor_print_ascii_art(c, "qxl/mono"); - } - break; default: fprintf(stderr, "%s: not implemented: type %d\n", __FUNCTION__, cursor->header.type); From b21330b513365a83aa808a27da1ebe53f8f10c3c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 28 Aug 2017 14:39:33 +0200 Subject: [PATCH 4/6] qxl: add support for chunked cursors. Signed-off-by: Gerd Hoffmann Message-id: 20170828123933.30323-3-kraxel@redhat.com --- hw/display/qxl-render.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c index e1b3f05ecb..90e0865618 100644 --- a/hw/display/qxl-render.c +++ b/hw/display/qxl-render.c @@ -204,7 +204,33 @@ void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie) g_free(cookie); } -static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor) +static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl, + QXLDataChunk *chunk, uint32_t group_id) +{ + uint32_t max_chunks = 32; + size_t offset = 0; + size_t bytes; + + for (;;) { + bytes = MIN(size - offset, chunk->data_size); + memcpy(dest + offset, chunk->data, bytes); + offset += bytes; + if (offset == size) { + return; + } + chunk = qxl_phys2virt(qxl, chunk->next_chunk, group_id); + if (!chunk) { + return; + } + max_chunks--; + if (max_chunks == 0) { + return; + } + } +} + +static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor, + uint32_t group_id) { QEMUCursor *c; size_t size; @@ -215,7 +241,7 @@ static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor) switch (cursor->header.type) { case SPICE_CURSOR_TYPE_ALPHA: size = sizeof(uint32_t) * cursor->header.width * cursor->header.height; - memcpy(c->data, cursor->chunk.data, size); + qxl_unpack_chunks(c->data, size, qxl, &cursor->chunk, group_id); if (qxl->debug > 2) { cursor_print_ascii_art(c, "qxl/alpha"); } @@ -259,11 +285,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext) if (!cursor) { return 1; } - if (cursor->chunk.data_size != cursor->data_size) { - fprintf(stderr, "%s: multiple chunks\n", __FUNCTION__); - return 1; - } - c = qxl_cursor(qxl, cursor); + c = qxl_cursor(qxl, cursor, ext->group_id); if (c == NULL) { c = cursor_builtin_left_ptr(); } From 138bc2df843105edb22978284fc2e16307f16211 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Fri, 4 Aug 2017 12:33:29 +0100 Subject: [PATCH 5/6] vga/migration: Update memory map in post_load After migration the chain4 alias mapping added by 80763888 (in 2011) might be missing, since there's no call to vga_update_memory_access in the post_load after the registers are updated. Add it back. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Juan Quintela Message-id: 20170804113329.13609-1-dgilbert@redhat.com Signed-off-by: Gerd Hoffmann --- hw/display/vga.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/display/vga.c b/hw/display/vga.c index 6fc8c8708a..ed24ef7076 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -2050,6 +2050,7 @@ static int vga_common_post_load(void *opaque, int version_id) /* force refresh */ s->graphic_mode = -1; vbe_update_vgaregs(s); + vga_update_memory_access(s); return 0; } From 79d16c21a565927943486b26789caa62413ff371 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 6 Sep 2017 16:20:58 +0200 Subject: [PATCH 6/6] virtio-gpu: don't clear QemuUIInfo information on reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't reset window layout information (passed via virtio_gpu_ui_info) on device reset, so the user interface window layout will be kept intact over reboots. The head size and position was commented out already, so this patch just drops the dead code. Additionally the enabled head mask must be kept so multihead setups work properly too. Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1460595 Signed-off-by: Gerd Hoffmann Reviewed-by: Marc-André Lureau Message-id: 20170906142058.2460-1-kraxel@redhat.com --- hw/display/virtio-gpu.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index f0761cf18b..622ee300f9 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -1195,17 +1195,6 @@ static void virtio_gpu_reset(VirtIODevice *vdev) virtio_gpu_resource_destroy(g, res); } for (i = 0; i < g->conf.max_outputs; i++) { -#if 0 - g->req_state[i].x = 0; - g->req_state[i].y = 0; - if (i == 0) { - g->req_state[0].width = 1024; - g->req_state[0].height = 768; - } else { - g->req_state[i].width = 0; - g->req_state[i].height = 0; - } -#endif g->scanout[i].resource_id = 0; g->scanout[i].width = 0; g->scanout[i].height = 0; @@ -1213,7 +1202,6 @@ static void virtio_gpu_reset(VirtIODevice *vdev) g->scanout[i].y = 0; g->scanout[i].ds = NULL; } - g->enabled_output_bitmask = 1; #ifdef CONFIG_VIRGL if (g->use_virgl_renderer) {