Message ID | 1411475457-10942-3-git-send-email-kraxel@redhat.com |
---|---|
State | New |
Headers | show |
On Tue, Sep 23, 2014 at 02:30:56PM +0200, Gerd Hoffmann wrote: > From: Benjamin Herrenschmidt <benh@kernel.crashing.org> > > Include the endian state in the migration stream as an optional > subsection which we only include when the endian isn't the default, > thus enabling backward compatibility of the common case. > > Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> > > Changes by kraxel: > * Remove bochs dispi interface changes. We'll do that in > a different way to make sure we don't conflict with > possible future bochs dispi interface changes. > * keep live migration bits. > > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> > --- > hw/display/vga.c | 41 +++++++++++++++++++++++++++++++++++++---- > hw/display/vga_int.h | 4 +++- > 2 files changed, 40 insertions(+), 5 deletions(-) > > diff --git a/hw/display/vga.c b/hw/display/vga.c > index 3f02984..fd16806 100644 > --- a/hw/display/vga.c > +++ b/hw/display/vga.c > @@ -1508,7 +1508,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) > 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->last_byteswap != byteswap) { > if (depth == 32 || (depth == 16 && !byteswap)) { > pixman_format_code_t format = > qemu_default_pixman_format(depth, !byteswap); > @@ -1526,6 +1527,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) > s->last_height = height; > s->last_line_offset = s->line_offset; > s->last_depth = depth; > + s->last_byteswap = byteswap; > full_update = 1; > } else if (is_buffer_shared(surface) && > (full_update || surface_data(surface) != s->vram_ptr > @@ -1789,6 +1791,7 @@ void vga_common_reset(VGACommonState *s) > s->cursor_start = 0; > s->cursor_end = 0; > s->cursor_offset = 0; > + s->big_endian_fb = s->default_endian_fb; > memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table)); > memset(s->last_palette, '\0', sizeof(s->last_palette)); > memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr)); > @@ -2020,6 +2023,28 @@ static int vga_common_post_load(void *opaque, int version_id) > return 0; > } > > +static bool vga_endian_state_needed(void *opaque) > +{ > + VGACommonState *s = opaque; > + > + /* > + * Only send the endian state if it's different from the > + * default one, thus ensuring backward compatibility for > + * migration of the common case > + */ > + return s->default_endian_fb != s->big_endian_fb; > +} > + > +const VMStateDescription vmstate_vga_endian = { > + .name = "vga.endian", > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_UINT8_EQUAL(big_endian_fb, VGACommonState), I don't think this is right. If I'm remembering how the vmstate macros work, this will abort if big_endian_fb isn't equal on source and destination. Which means as soon as it's possible to actually change the big_endian_fb value, migrations will start failing/ I think this should instead be VMSTATE_BOOL() [snip] > - bool big_endian_fb; > + uint8_t big_endian_fb; > + uint8_t default_endian_fb; > /* hardware mouse cursor support */ > uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; > void (*cursor_invalidate)(struct VGACommonState *s); In which case you also don't need to change the type of the big_endian_fb field.
diff --git a/hw/display/vga.c b/hw/display/vga.c index 3f02984..fd16806 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1508,7 +1508,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) 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->last_byteswap != byteswap) { if (depth == 32 || (depth == 16 && !byteswap)) { pixman_format_code_t format = qemu_default_pixman_format(depth, !byteswap); @@ -1526,6 +1527,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) s->last_height = height; s->last_line_offset = s->line_offset; s->last_depth = depth; + s->last_byteswap = byteswap; full_update = 1; } else if (is_buffer_shared(surface) && (full_update || surface_data(surface) != s->vram_ptr @@ -1789,6 +1791,7 @@ void vga_common_reset(VGACommonState *s) s->cursor_start = 0; s->cursor_end = 0; s->cursor_offset = 0; + s->big_endian_fb = s->default_endian_fb; memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table)); memset(s->last_palette, '\0', sizeof(s->last_palette)); memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr)); @@ -2020,6 +2023,28 @@ static int vga_common_post_load(void *opaque, int version_id) return 0; } +static bool vga_endian_state_needed(void *opaque) +{ + VGACommonState *s = opaque; + + /* + * Only send the endian state if it's different from the + * default one, thus ensuring backward compatibility for + * migration of the common case + */ + return s->default_endian_fb != s->big_endian_fb; +} + +const VMStateDescription vmstate_vga_endian = { + .name = "vga.endian", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8_EQUAL(big_endian_fb, VGACommonState), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_vga_common = { .name = "vga", .version_id = 2, @@ -2056,6 +2081,14 @@ const VMStateDescription vmstate_vga_common = { VMSTATE_UINT32(vbe_line_offset, VGACommonState), VMSTATE_UINT32(vbe_bank_mask, VGACommonState), VMSTATE_END_OF_LIST() + }, + .subsections = (VMStateSubsection []) { + { + .vmsd = &vmstate_vga_endian, + .needed = vga_endian_state_needed, + }, { + /* empty */ + } } }; @@ -2126,14 +2159,14 @@ void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate) } /* - * Set default fb endian based on target, should probably be turned + * Set default fb endian based on target, could probably be turned * into a device attribute set by the machine/platform to remove * all target endian dependencies from this file. */ #ifdef TARGET_WORDS_BIGENDIAN - s->big_endian_fb = true; + s->default_endian_fb = true; #else - s->big_endian_fb = false; + s->default_endian_fb = false; #endif vga_dirty_log_start(s); } diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h index 28d67cf..e44b4a7 100644 --- a/hw/display/vga_int.h +++ b/hw/display/vga_int.h @@ -150,6 +150,7 @@ typedef struct VGACommonState { uint32_t last_width, last_height; /* in chars or pixels */ uint32_t last_scr_width, last_scr_height; /* in pixels */ uint32_t last_depth; /* in bits */ + bool last_byteswap; uint8_t cursor_start, cursor_end; bool cursor_visible_phase; int64_t cursor_blink_time; @@ -157,7 +158,8 @@ typedef struct VGACommonState { const GraphicHwOps *hw_ops; bool full_update_text; bool full_update_gfx; - bool big_endian_fb; + uint8_t big_endian_fb; + uint8_t default_endian_fb; /* hardware mouse cursor support */ uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; void (*cursor_invalidate)(struct VGACommonState *s);