From 3dcd9a4508f67ca12bc60a0509dc0fb2061df526 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Apr 09 2009 15:08:34 +0000 Subject: - Add a much cleaner fix for vga segfault (#494002) --- diff --git a/qemu-fix-display-breakage.patch b/qemu-fix-display-breakage.patch index d2e6de1..8645bc2 100644 --- a/qemu-fix-display-breakage.patch +++ b/qemu-fix-display-breakage.patch @@ -1,543 +1,35 @@ -From 8ad63a93a482d5c3354b97463633394456a157d5 Mon Sep 17 00:00:00 2001 -From: Avi Kivity -Date: Thu, 2 Apr 2009 22:17:50 +0300 -Subject: [PATCH 1/1] kvm: qemu: Fix display breakage when resizing the screen +From 9d1b494a2d5dd2c129994edcf4eb7630bb554964 Mon Sep 17 00:00:00 2001 +From: aliguori +Date: Tue, 7 Apr 2009 20:55:58 +0000 +Subject: [PATCH 1/1] Fix crash on resolution change -> screen dump -> vga redraw (Avi Kivity) -When the vga resolution changes, a new display surface is not allocated -immediately; instead that is deferred until the next update. However, -if we're running without a display client attached, that won't happen -and the next bitblt is likely to cause a segfault by overflowing the -display surface. +The vga screen dump function updates last_width and last_height, +but does not change the DisplaySurface that these variables describe. +A consequent vga_draw_graphic() will therefore fail to resize the +surface and crash. -Fix by reallocating the display immediately when the resolution changes. +Fix by invalidating the display state after a screen dump, forcing +vga_draw_graphic() to reallocate the DisplaySurface. Signed-off-by: Avi Kivity +Signed-off-by: Anthony Liguori + + +git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7026 c046a42c-6fe2-441c-8c8c-71466251a162 --- - qemu/hw/cirrus_vga.c | 10 ++- - qemu/hw/vga.c | 205 +++++++++++++++++++++++++++++-------------------- - qemu/hw/vga_int.h | 4 + - 3 files changed, 134 insertions(+), 85 deletions(-) + qemu/hw/vga.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) -diff --git a/qemu/hw/cirrus_vga.c b/qemu/hw/cirrus_vga.c -index 0ab0f14..7bd0482 100644 ---- a/qemu/hw/cirrus_vga.c -+++ b/qemu/hw/cirrus_vga.c -@@ -1399,6 +1399,8 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) - break; - } - -+ vga_update_resolution((VGAState *)s); -+ - return CIRRUS_HOOK_HANDLED; - } - -@@ -1426,6 +1428,7 @@ static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value) - #endif - } - s->cirrus_hidden_dac_lockindex = 0; -+ vga_update_resolution((VGAState *)s); - } - - /*************************************** -@@ -1712,6 +1715,8 @@ cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value) - break; - } - -+ vga_update_resolution((VGAState *)s); -+ - return CIRRUS_HOOK_HANDLED; - } - -@@ -2839,6 +2844,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) - if (s->ar_flip_flop == 0) { - val &= 0x3f; - s->ar_index = val; -+ vga_update_resolution((VGAState *)s); - } else { - index = s->ar_index & 0x1f; - switch (index) { -@@ -2932,6 +2938,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) - /* can always write bit 4 of CR7 */ - if (s->cr_index == 7) - s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10); -+ vga_update_resolution((VGAState *)s); - return; - } - switch (s->cr_index) { -@@ -3166,7 +3173,8 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id) - - cirrus_update_memory_access(s); - /* force refresh */ -- s->graphic_mode = -1; -+ vga_update_resolution((VGAState *)s); -+ s->want_full_update = 1; - cirrus_update_bank_ptr(s, 0); - cirrus_update_bank_ptr(s, 1); - return 0; diff --git a/qemu/hw/vga.c b/qemu/hw/vga.c -index d4fddf9..9a950d3 100644 +index b1e4373..4d1049b 100644 --- a/qemu/hw/vga.c +++ b/qemu/hw/vga.c -@@ -37,6 +37,10 @@ - - //#define DEBUG_BOCHS_VBE - -+#define GMODE_TEXT 0 -+#define GMODE_GRAPH 1 -+#define GMODE_BLANK 2 -+ - /* force some bits to zero */ - const uint8_t sr_mask[8] = { - (uint8_t)~0xfc, -@@ -394,6 +398,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) - if (s->ar_flip_flop == 0) { - val &= 0x3f; - s->ar_index = val; -+ vga_update_resolution(s); - } else { - index = s->ar_index & 0x1f; - switch(index) { -@@ -434,6 +439,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) - #endif - s->sr[s->sr_index] = val & sr_mask[s->sr_index]; - if (s->sr_index == 1) s->update_retrace_info(s); -+ vga_update_resolution(s); - break; - case 0x3c7: - s->dac_read_index = val; -@@ -461,6 +467,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) - printf("vga: write GR%x = 0x%02x\n", s->gr_index, val); - #endif - s->gr[s->gr_index] = val & gr_mask[s->gr_index]; -+ vga_update_resolution(s); - break; - case 0x3b4: - case 0x3d4: -@@ -476,6 +483,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) - /* can always write bit 4 of CR7 */ - if (s->cr_index == 7) - s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10); -+ vga_update_resolution(s); - return; - } - switch(s->cr_index) { -@@ -503,6 +511,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) - s->update_retrace_info(s); - break; - } -+ vga_update_resolution(s); - break; - case 0x3ba: - case 0x3da: -@@ -582,11 +591,13 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) - if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) { - s->vbe_regs[s->vbe_index] = val; - } -+ vga_update_resolution(s); - break; - case VBE_DISPI_INDEX_YRES: - if (val <= VBE_DISPI_MAX_YRES) { - s->vbe_regs[s->vbe_index] = val; - } -+ vga_update_resolution(s); - break; - case VBE_DISPI_INDEX_BPP: - if (val == 0) -@@ -595,6 +606,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) - val == 16 || val == 24 || val == 32) { - s->vbe_regs[s->vbe_index] = val; - } -+ vga_update_resolution(s); - break; - case VBE_DISPI_INDEX_BANK: - if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) { -@@ -663,6 +675,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) - } - s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0; - s->vbe_regs[s->vbe_index] = val; -+ vga_update_resolution(s); - break; - case VBE_DISPI_INDEX_VIRT_WIDTH: - { -@@ -683,6 +696,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) - s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h; - s->vbe_line_offset = line_offset; - } -+ vga_update_resolution(s); - break; - case VBE_DISPI_INDEX_X_OFFSET: - case VBE_DISPI_INDEX_Y_OFFSET: -@@ -697,6 +711,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) - s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3); - s->vbe_start_addr >>= 2; - } -+ vga_update_resolution(s); - break; - default: - break; -@@ -1300,7 +1315,6 @@ static void vga_draw_text(VGAState *s, int full_update) - s->plane_updated = 0; - full_update = 1; - } -- full_update |= update_basic_params(s); - - line_offset = s->line_offset; - s1 = s->vram_ptr + (s->start_addr * 4); -@@ -1312,18 +1326,6 @@ static void vga_draw_text(VGAState *s, int full_update) - return; - } - -- if (width != s->last_width || height != s->last_height || -- cw != s->last_cw || cheight != s->last_ch || s->last_depth) { -- s->last_scr_width = width * cw; -- s->last_scr_height = height * cheight; -- qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height); -- s->last_depth = 0; -- s->last_width = width; -- s->last_height = height; -- s->last_ch = cheight; -- s->last_cw = cw; -- full_update = 1; -- } - s->rgb_to_pixel = - rgb_to_pixel_dup_table[get_depth_index(s->ds)]; - full_update |= update_palette16(s); -@@ -1580,40 +1582,20 @@ static void vga_sync_dirty_bitmap(VGAState *s) - vga_dirty_log_start(s); - } - --/* -- * graphic modes -- */ --static void vga_draw_graphic(VGAState *s, int full_update) -+static void vga_update_resolution_graphics(VGAState *s) - { -- int y1, y, update, linesize, y_start, double_scan, mask, depth; -- int width, height, shift_control, line_offset, bwidth, bits; -+ int depth = s->get_bpp(s); -+ int width, height, shift_control, double_scan; - int disp_width, multi_scan, multi_run; -- uint8_t *d; -- uint32_t v, addr1, addr; -- long page0, page1, page_min, page_max; -- vga_draw_line_func *vga_draw_line; -- -- full_update |= update_basic_params(s); -- -- if (!full_update) -- vga_sync_dirty_bitmap(s); - - s->get_resolution(s, &width, &height); -- disp_width = width; - - shift_control = (s->gr[0x05] >> 5) & 3; - double_scan = (s->cr[0x09] >> 7); -- if (shift_control != 1) { -- multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1; -- } else { -- /* in CGA modes, multi_scan is ignored */ -- /* XXX: is it correct ? */ -- multi_scan = double_scan; -- } -- multi_run = multi_scan; -+ - if (shift_control != s->shift_control || - double_scan != s->double_scan) { -- full_update = 1; -+ s->want_full_update = 1; - s->shift_control = shift_control; - s->double_scan = double_scan; - } -@@ -1627,12 +1609,25 @@ static void vga_draw_graphic(VGAState *s, int full_update) - disp_width <<= 1; - } - } -+ disp_width = width; -+ -+ if (shift_control != 1) { -+ multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1; -+ } else { -+ /* in CGA modes, multi_scan is ignored */ -+ /* XXX: is it correct ? */ -+ multi_scan = double_scan; -+ } -+ -+ multi_run = multi_scan; - -- depth = s->get_bpp(s); - if (s->line_offset != s->last_line_offset || - disp_width != s->last_width || - height != s->last_height || -- s->last_depth != depth) { -+ s->last_depth != depth || -+ s->multi_run != multi_run || -+ s->multi_scan != multi_scan || -+ s->want_full_update) { - #if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) - if (depth == 16 || depth == 32) { - #else -@@ -1659,8 +1654,74 @@ static void vga_draw_graphic(VGAState *s, int full_update) - s->last_height = height; - s->last_line_offset = s->line_offset; - s->last_depth = depth; -- full_update = 1; -- } else if (is_graphic_console() && is_buffer_shared(s->ds->surface) && -+ s->multi_run = multi_run; -+ s->multi_scan = multi_scan; -+ s->want_full_update = 1; -+ } -+} -+ -+static void vga_update_resolution_text(VGAState *s) -+{ -+ int width, height, cw, cheight; -+ -+ vga_get_text_resolution(s, &width, &height, &cw, &cheight); -+ if (width != s->last_width || height != s->last_height || -+ cw != s->last_cw || cheight != s->last_ch || s->last_depth) { -+ s->last_scr_width = width * cw; -+ s->last_scr_height = height * cheight; -+ qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height); -+ s->last_depth = 0; -+ s->last_width = width; -+ s->last_height = height; -+ s->last_ch = cheight; -+ s->last_cw = cw; -+ s->want_full_update = 1; -+ } -+} -+ -+void vga_update_resolution(VGAState *s) -+{ -+ int graphic_mode; -+ -+ if (!(s->ar_index & 0x20)) { -+ graphic_mode = GMODE_BLANK; -+ } else { -+ graphic_mode = s->gr[6] & 1; -+ } -+ if (graphic_mode != s->graphic_mode) { -+ s->graphic_mode = graphic_mode; -+ s->want_full_update = 1; -+ } -+ s->want_full_update |= update_basic_params(s); -+ switch (graphic_mode) { -+ case GMODE_TEXT: -+ vga_update_resolution_text(s); -+ break; -+ case GMODE_GRAPH: -+ vga_update_resolution_graphics(s); -+ break; -+ } -+} -+ -+/* -+ * graphic modes -+ */ -+static void vga_draw_graphic(VGAState *s, int full_update) -+{ -+ int y1, y, update, linesize, y_start, mask; -+ int width, height, line_offset, bwidth, bits; -+ int multi_run; -+ uint8_t *d; -+ uint32_t v, addr1, addr; -+ long page0, page1, page_min, page_max; -+ vga_draw_line_func *vga_draw_line; -+ -+ if (!full_update) -+ vga_sync_dirty_bitmap(s); -+ -+ s->get_resolution(s, &width, &height); -+ multi_run = s->multi_run; -+ if (is_graphic_console() && is_buffer_shared(s->ds->surface) && - (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) { - s->ds->surface->data = s->vram_ptr + (s->start_addr * 4); - dpy_setdata(s->ds); -@@ -1669,7 +1730,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) - s->rgb_to_pixel = - rgb_to_pixel_dup_table[get_depth_index(s->ds)]; - -- if (shift_control == 0) { -+ if (s->shift_control == 0) { - full_update |= update_palette16(s); - if (s->sr[0x01] & 8) { - v = VGA_DRAW_LINE4D2; -@@ -1677,7 +1738,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) - v = VGA_DRAW_LINE4; - } - bits = 4; -- } else if (shift_control == 1) { -+ } else if (s->shift_control == 1) { - full_update |= update_palette16(s); - if (s->sr[0x01] & 8) { - v = VGA_DRAW_LINE2D2; -@@ -1773,7 +1834,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) - if (y_start >= 0) { - /* flush to display */ - dpy_update(s->ds, 0, y_start, -- disp_width, y - y_start); -+ s->last_width, y - y_start); - y_start = -1; - } - } -@@ -1782,7 +1843,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) - if ((y1 & mask) == mask) - addr1 += line_offset; - y1++; -- multi_run = multi_scan; -+ multi_run = s->multi_scan; - } else { - multi_run--; - } -@@ -1794,7 +1855,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) - if (y_start >= 0) { - /* flush to display */ - dpy_update(s->ds, 0, y_start, -- disp_width, y - y_start); -+ s->last_width, y - y_start); - } - /* reset modified pages */ - if (page_max != -1) { -@@ -1831,29 +1892,17 @@ static void vga_draw_blank(VGAState *s, int full_update) - s->last_scr_width, s->last_scr_height); - } - --#define GMODE_TEXT 0 --#define GMODE_GRAPH 1 --#define GMODE_BLANK 2 -- - static void vga_update_display(void *opaque) - { - VGAState *s = (VGAState *)opaque; -- int full_update, graphic_mode; -+ int full_update; - - if (ds_get_bits_per_pixel(s->ds) == 0) { - /* nothing to do */ - } else { -- full_update = 0; -- if (!(s->ar_index & 0x20)) { -- graphic_mode = GMODE_BLANK; -- } else { -- graphic_mode = s->gr[6] & 1; -- } -- if (graphic_mode != s->graphic_mode) { -- s->graphic_mode = graphic_mode; -- full_update = 1; -- } -- switch(graphic_mode) { -+ full_update = s->want_full_update; -+ s->want_full_update = 0; -+ switch(s->graphic_mode) { - case GMODE_TEXT: - vga_draw_text(s, full_update); - break; -@@ -1876,8 +1925,8 @@ static void vga_invalidate_display(void *opaque) - { - VGAState *s = (VGAState *)opaque; - -- s->last_width = -1; -- s->last_height = -1; -+ vga_update_resolution(s); -+ s->want_full_update = 1; - } - - void vga_reset(void *opaque) -@@ -1921,7 +1970,6 @@ void vga_reset(void *opaque) - s->vbe_bank_mask = (s->vram_size >> 16) - 1; - #endif - memset(s->font_offsets, '\0', sizeof(s->font_offsets)); -- s->graphic_mode = -1; /* force full update */ - s->shift_control = 0; - s->double_scan = 0; - s->line_offset = 0; -@@ -1947,6 +1995,7 @@ void vga_reset(void *opaque) - memset(&s->retrace_info, 0, sizeof (s->retrace_info)); - break; - } -+ vga_update_resolution(s); - } - - #define TEXTMODE_X(x) ((x) % width) -@@ -1965,24 +2014,9 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) - char msg_buffer[80]; - int full_update = 0; - -- if (!(s->ar_index & 0x20)) { -- graphic_mode = GMODE_BLANK; -- } else { -- graphic_mode = s->gr[6] & 1; -- } -- if (graphic_mode != s->graphic_mode) { -- s->graphic_mode = graphic_mode; -- full_update = 1; -- } -- if (s->last_width == -1) { -- s->last_width = 0; -- full_update = 1; -- } -- - switch (graphic_mode) { - case GMODE_TEXT: - /* TODO: update palette */ -- full_update |= update_basic_params(s); - - /* total width & height */ - cheight = (s->cr[9] & 0x1f) + 1; -@@ -2224,7 +2258,8 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id) - #endif - - /* force refresh */ -- s->graphic_mode = -1; -+ vga_update_resolution(s); -+ s->want_full_update = 1; - return 0; - } - -@@ -2418,7 +2453,8 @@ void vga_bios_init(VGAState *s) - memcpy(s->palette, palette_model, 192); - - s->bank_offset = 0; -- s->graphic_mode = -1; -+ vga_update_resolution(s); -+ s->want_full_update = 1; - - /* TODO: add vbe support if enabled */ +@@ -2678,4 +2678,5 @@ static void vga_screen_dump(void *opaque, const char *filename) + vga_screen_dump_graphic(s, filename); + else + vga_screen_dump_text(s, filename); ++ vga_invalidate_display(s); } -@@ -2803,7 +2839,8 @@ static void vga_screen_dump_common(VGAState *s, const char *filename, - ds->surface = qemu_create_displaysurface(w, h, 32, 4 * w); - - s->ds = ds; -- s->graphic_mode = -1; -+ vga_update_resolution(s); -+ s->want_full_update = 1; - vga_update_display(s); - - ppm_save(filename, ds->surface); -diff --git a/qemu/hw/vga_int.h b/qemu/hw/vga_int.h -index 8ba8a60..71ffeb5 100644 ---- a/qemu/hw/vga_int.h -+++ b/qemu/hw/vga_int.h -@@ -147,8 +147,11 @@ typedef void (* vga_update_retrace_info_fn)(struct VGAState *s); - DisplayState *ds; \ - uint32_t font_offsets[2]; \ - int graphic_mode; \ -+ int want_full_update; \ - uint8_t shift_control; \ - uint8_t double_scan; \ -+ uint8_t multi_run; \ -+ uint8_t multi_scan; \ - uint32_t line_offset; \ - uint32_t line_compare; \ - uint32_t start_addr; \ -@@ -195,6 +198,7 @@ void vga_common_init(VGAState *s, uint8_t *vga_ram_base, - ram_addr_t vga_ram_offset, int vga_ram_size); - void vga_init(VGAState *s); - void vga_reset(void *s); -+void vga_update_resolution(VGAState *s); - - void vga_dirty_log_start(VGAState *s); - void vga_dirty_log_stop(VGAState *s); -- 1.6.0.6 diff --git a/qemu.spec b/qemu.spec index 1b5308e..56ea58b 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,7 +1,7 @@ Summary: QEMU is a FAST! processor emulator Name: qemu Version: 0.10 -Release: 6%{?dist} +Release: 7%{?dist} # I have mistakenly thought the revision name would be 1.0. # So 0.10 series get Epoch = 1 Epoch: 2 @@ -457,6 +457,9 @@ fi %{_mandir}/man1/qemu-img.1* %changelog +* Thu Apr 9 2009 Mark McLoughlin - 2:0.10-7 +- Add a much cleaner fix for vga segfault (#494002) + * Sun Apr 5 2009 Glauber Costa - 2:0.10-6 - Fixed qcow2 segfault creating disks over 2TB. #491943