cirrus: bugfixes, with some vga cleanups.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJZ5b5FAAoJEEy22O7T6HE4UugQAK1Y4PabCrOGFs1FYe/tCCvf
 kMLa7iWRoXWE9gPMArHQ4XURC6sZ54g+MOGZFWp7VdHTdkXsID8BDB60G2h0P5Gg
 IZxSrw+7k1u7plc/LzjFfwryGsAEm6Buj2FbA79XvMUr+6IS8MH2UpsrP5KJbqsQ
 19a0GIYRly92UOmfdiKBH5lZ5XAv2BlPihUFB7gNesZmoQd11opQIwdTixFY9LBs
 viS5ntrQX1G4rIfuhuyk16TlL+aOX+zk1W0MOoPvASt9s0pv836gJ2dTRkDUHpic
 89ORr8QdBE2/ODT9H0aWxKsb/txEKRCuPB+2YIf9JtOCHltCW1sOUdmqcN7jVtU7
 rEF6AlF0zTtdRGbzWcEAoXW+FBa9YQtxXtrYNLLkiySE+Wj5BNi0bKRCbRr1APCg
 pMCruCtp3MYRVZKRVG5WO4Tb1NSoLG5W95iIh5qdGX99bqkJ4hD6R8x/5d6CMVR2
 q5iiO1HjOzAkWjhFEbq2NhvSaxaZeGt/Dm6cL/p8hBPSiZzkeJ1AqfvzjOjez3pJ
 G0MBHkD8o53cdDMrjnwl1zv2pq5aR//4FR1XffpSTeziWpnzu/nxSNIN5oKS3FJ3
 4AsePk4CA29Wq4QJUZzf+LgQZIRRBRLhTIuIUL9izq6BRA2QAyCF5QPvxed1jAQ+
 HjRYrQEbbY7VPFpZa70T
 =hdje
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kraxel/tags/vga-20171017-pull-request' into staging

cirrus: bugfixes, with some vga cleanups.

# gpg: Signature made Tue 17 Oct 2017 09:24:37 BST
# gpg:                using RSA key 0x4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/vga-20171017-pull-request:
  cirrus: fix oob access in mode4and5 write functions
  vga: add ram_addr_t cast
  vga: handle cirrus vbe mode wraparounds.
  vga: drop line_offset variable

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2017-10-19 10:53:19 +01:00
commit 73b733e690
2 changed files with 25 additions and 14 deletions

View File

@ -2038,15 +2038,14 @@ static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
unsigned val = mem_value;
uint8_t *dst;
dst = s->vga.vram_ptr + (offset &= s->cirrus_addr_mask);
for (x = 0; x < 8; x++) {
dst = s->vga.vram_ptr + ((offset + x) & s->cirrus_addr_mask);
if (val & 0x80) {
*dst = s->cirrus_shadow_gr1;
} else if (mode == 5) {
*dst = s->cirrus_shadow_gr0;
}
val <<= 1;
dst++;
}
memory_region_set_dirty(&s->vga.vram, offset, 8);
}
@ -2060,8 +2059,8 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
unsigned val = mem_value;
uint8_t *dst;
dst = s->vga.vram_ptr + (offset &= s->cirrus_addr_mask);
for (x = 0; x < 8; x++) {
dst = s->vga.vram_ptr + ((offset + 2 * x) & s->cirrus_addr_mask & ~1);
if (val & 0x80) {
*dst = s->cirrus_shadow_gr1;
*(dst + 1) = s->vga.gr[0x11];
@ -2070,7 +2069,6 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
*(dst + 1) = s->vga.gr[0x10];
}
val <<= 1;
dst += 2;
}
memory_region_set_dirty(&s->vga.vram, offset, 16);
}

View File

@ -1464,14 +1464,14 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
{
DisplaySurface *surface = qemu_console_surface(s->con);
int y1, y, update, linesize, y_start, double_scan, mask, depth;
int width, height, shift_control, line_offset, bwidth, bits;
ram_addr_t page0, page1;
int width, height, shift_control, bwidth, bits;
ram_addr_t page0, page1, region_start, region_end;
DirtyBitmapSnapshot *snap = NULL;
int disp_width, multi_scan, multi_run;
uint8_t *d;
uint32_t v, addr1, addr;
vga_draw_line_func *vga_draw_line = NULL;
bool share_surface;
bool share_surface, force_shadow = false;
pixman_format_code_t format;
#ifdef HOST_WORDS_BIGENDIAN
bool byteswap = !s->big_endian_fb;
@ -1484,6 +1484,15 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
s->get_resolution(s, &width, &height);
disp_width = width;
region_start = (s->start_addr * 4);
region_end = region_start + (ram_addr_t)s->line_offset * height;
if (region_end > s->vbe_size) {
/* wraps around (can happen with cirrus vbe modes) */
region_start = 0;
region_end = s->vbe_size;
force_shadow = true;
}
shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
if (shift_control != 1) {
@ -1523,7 +1532,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
format = qemu_default_pixman_format(depth, !byteswap);
if (format) {
share_surface = dpy_gfx_check_format(s->con, format)
&& !s->force_shadow;
&& !s->force_shadow && !force_shadow;
} else {
share_surface = false;
}
@ -1614,7 +1623,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
s->cursor_invalidate(s);
}
line_offset = s->line_offset;
#if 0
printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
@ -1628,8 +1636,6 @@ 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);
if (s->line_compare < height) {
/* split screen mode */
@ -1652,10 +1658,17 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
addr = (addr & ~0x8000) | ((y1 & 2) << 14);
}
update = full_update;
page0 = addr;
page1 = addr + bwidth - 1;
page0 = addr & s->vbe_size_mask;
page1 = (addr + bwidth - 1) & s->vbe_size_mask;
if (full_update) {
update = 1;
} else if (page1 < page0) {
/* scanline wraps from end of video memory to the start */
assert(force_shadow);
update = memory_region_snapshot_get_dirty(&s->vram, snap,
page0, 0);
update |= memory_region_snapshot_get_dirty(&s->vram, snap,
page1, 0);
} else {
update = memory_region_snapshot_get_dirty(&s->vram, snap,
page0, page1 - page0);
@ -1681,7 +1694,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
if (!multi_run) {
mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
if ((y1 & mask) == mask)
addr1 += line_offset;
addr1 += s->line_offset;
y1++;
multi_run = multi_scan;
} else {