* lsi53c895a: fix assertion failure with invalid Block Move

* vga: fix assertion failure with 4- and 16-color modes
 * remove unnecessary assignment
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmYNKboUHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroNMDgf/Wgw+qNkNooAhEH1V5l0xdyiF4QQU
 stz4kcKdWkQB5dsVy8utC3nN2baRFPgj6Utr2e8FqzxGuY8qYL3olh8k1ygiFiFz
 joSOxAlBuRUOsJq90EJUyGeFykJ/F/neJ2n6VjOtKyry9c8PnInjmuNMFYsxeLow
 j1VF6defALut/8wvxPm5WmfFzS1Hv3I9k/GqKSlAjNpY2COlibshEoNFuZZtpfeI
 JnUL5oB+sICoZH2/mM5a9Nv2z0NCHAwKF7alXVjfHWvdaRQO6bLlraDmPXmh0ZMY
 MsoULMQaeZCtC0vfc8XJZj/C/s2iO14gfqA23/mfGCLalyo7l1yh4e6JyQ==
 =xDOl
 -----END PGP SIGNATURE-----

Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging

* lsi53c895a: fix assertion failure with invalid Block Move
* vga: fix assertion failure with 4- and 16-color modes
* remove unnecessary assignment

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmYNKboUHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroNMDgf/Wgw+qNkNooAhEH1V5l0xdyiF4QQU
# stz4kcKdWkQB5dsVy8utC3nN2baRFPgj6Utr2e8FqzxGuY8qYL3olh8k1ygiFiFz
# joSOxAlBuRUOsJq90EJUyGeFykJ/F/neJ2n6VjOtKyry9c8PnInjmuNMFYsxeLow
# j1VF6defALut/8wvxPm5WmfFzS1Hv3I9k/GqKSlAjNpY2COlibshEoNFuZZtpfeI
# JnUL5oB+sICoZH2/mM5a9Nv2z0NCHAwKF7alXVjfHWvdaRQO6bLlraDmPXmh0ZMY
# MsoULMQaeZCtC0vfc8XJZj/C/s2iO14gfqA23/mfGCLalyo7l1yh4e6JyQ==
# =xDOl
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 03 Apr 2024 11:04:42 BST
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* tag 'for-upstream' of https://gitlab.com/bonzini/qemu:
  pc_q35: remove unnecessary m->alias assignment
  lsi53c895a: avoid out of bounds access to s->msg[]
  vga: do not treat horiz pel panning value of 8 as "enabled"
  vga: adjust dirty memory region if pel panning is active
  vga: move computation of dirty memory region later
  vga: merge conditionals on shift control register

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2024-04-03 12:52:03 +01:00
commit 786fd793b8
3 changed files with 85 additions and 81 deletions

View file

@ -1501,31 +1501,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
disp_width = width;
depth = s->get_bpp(s);
region_start = (s->params.start_addr * 4);
region_end = region_start + (ram_addr_t)s->params.line_offset * height;
region_end += width * depth / 8; /* scanline length */
region_end -= s->params.line_offset;
if (region_end > s->vbe_size || depth == 0 || depth == 15) {
/*
* We land here on:
* - wraps around (can happen with cirrus vbe modes)
* - depth == 0 (256 color palette video mode)
* - depth == 15
*
* Take the safe and slow route:
* - create a dirty bitmap snapshot for all vga memory.
* - force shadowing (so all vga memory access goes
* through vga_read_*() helpers).
*
* Given this affects only vga features which are pretty much
* unused by modern guests there should be no performance
* impact.
*/
region_start = 0;
region_end = s->vbe_size;
force_shadow = true;
}
/* bits 5-6: 0 = 16-color mode, 1 = 4-color mode, 2 = 256-color mode. */
shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
@ -1546,13 +1521,86 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
}
if (shift_control == 0) {
full_update |= update_palette16(s);
if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
disp_width <<= 1;
v = VGA_DRAW_LINE4D2;
} else {
v = VGA_DRAW_LINE4;
}
bits = 4;
} else if (shift_control == 1) {
full_update |= update_palette16(s);
if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
disp_width <<= 1;
v = VGA_DRAW_LINE2D2;
} else {
v = VGA_DRAW_LINE2;
}
bits = 4;
} else {
switch (depth) {
default:
case 0:
full_update |= update_palette256(s);
v = VGA_DRAW_LINE8D2;
bits = 4;
break;
case 8:
full_update |= update_palette256(s);
v = VGA_DRAW_LINE8;
bits = 8;
break;
case 15:
v = s->big_endian_fb ? VGA_DRAW_LINE15_BE : VGA_DRAW_LINE15_LE;
bits = 16;
break;
case 16:
v = s->big_endian_fb ? VGA_DRAW_LINE16_BE : VGA_DRAW_LINE16_LE;
bits = 16;
break;
case 24:
v = s->big_endian_fb ? VGA_DRAW_LINE24_BE : VGA_DRAW_LINE24_LE;
bits = 24;
break;
case 32:
v = s->big_endian_fb ? VGA_DRAW_LINE32_BE : VGA_DRAW_LINE32_LE;
bits = 32;
break;
}
}
/* Horizontal pel panning bit 3 is only used in text mode. */
hpel = bits <= 8 ? s->params.hpel & 7 : 0;
region_start = (s->params.start_addr * 4);
region_end = region_start + (ram_addr_t)s->params.line_offset * height;
region_end += width * depth / 8; /* scanline length */
region_end -= s->params.line_offset;
if (hpel) {
region_end += 4;
}
if (region_end > s->vbe_size || depth == 0 || depth == 15) {
/*
* We land here on:
* - wraps around (can happen with cirrus vbe modes)
* - depth == 0 (256 color palette video mode)
* - depth == 15
*
* Take the safe and slow route:
* - create a dirty bitmap snapshot for all vga memory.
* - force shadowing (so all vga memory access goes
* through vga_read_*() helpers).
*
* Given this affects only vga features which are pretty much
* unused by modern guests there should be no performance
* impact.
*/
region_start = 0;
region_end = s->vbe_size;
force_shadow = true;
}
/*
@ -1607,53 +1655,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
}
}
if (shift_control == 0) {
full_update |= update_palette16(s);
if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
v = VGA_DRAW_LINE4D2;
} else {
v = VGA_DRAW_LINE4;
}
bits = 4;
} else if (shift_control == 1) {
full_update |= update_palette16(s);
if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
v = VGA_DRAW_LINE2D2;
} else {
v = VGA_DRAW_LINE2;
}
bits = 4;
} else {
switch(s->get_bpp(s)) {
default:
case 0:
full_update |= update_palette256(s);
v = VGA_DRAW_LINE8D2;
bits = 4;
break;
case 8:
full_update |= update_palette256(s);
v = VGA_DRAW_LINE8;
bits = 8;
break;
case 15:
v = s->big_endian_fb ? VGA_DRAW_LINE15_BE : VGA_DRAW_LINE15_LE;
bits = 16;
break;
case 16:
v = s->big_endian_fb ? VGA_DRAW_LINE16_BE : VGA_DRAW_LINE16_LE;
bits = 16;
break;
case 24:
v = s->big_endian_fb ? VGA_DRAW_LINE24_BE : VGA_DRAW_LINE24_LE;
bits = 24;
break;
case 32:
v = s->big_endian_fb ? VGA_DRAW_LINE32_BE : VGA_DRAW_LINE32_LE;
bits = 32;
break;
}
}
vga_draw_line = vga_draw_line_table[v];
if (!is_buffer_shared(surface) && s->cursor_invalidate) {
@ -1665,7 +1666,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
s->params.line_compare, sr(s, VGA_SEQ_CLOCK_MODE));
#endif
hpel = bits <= 8 ? s->params.hpel : 0;
addr1 = (s->params.start_addr * 4);
bwidth = DIV_ROUND_UP(width * bits, 8);
if (hpel) {

View file

@ -393,7 +393,6 @@ static void pc_q35_8_1_machine_options(MachineClass *m)
{
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_q35_8_2_machine_options(m);
m->alias = NULL;
pcmc->broken_32bit_mem_addr_check = true;
compat_props_add(m->compat_props, hw_compat_8_1, hw_compat_8_1_len);
compat_props_add(m->compat_props, pc_compat_8_1, pc_compat_8_1_len);

View file

@ -927,13 +927,18 @@ static void lsi_do_msgin(LSIState *s)
assert(len > 0 && len <= LSI_MAX_MSGIN_LEN);
if (len > s->dbc)
len = s->dbc;
pci_dma_write(PCI_DEVICE(s), s->dnad, s->msg, len);
/* Linux drivers rely on the last byte being in the SIDL. */
s->sidl = s->msg[len - 1];
s->msg_len -= len;
if (s->msg_len) {
memmove(s->msg, s->msg + len, s->msg_len);
} else {
if (len) {
pci_dma_write(PCI_DEVICE(s), s->dnad, s->msg, len);
/* Linux drivers rely on the last byte being in the SIDL. */
s->sidl = s->msg[len - 1];
s->msg_len -= len;
if (s->msg_len) {
memmove(s->msg, s->msg + len, s->msg_len);
}
}
if (!s->msg_len) {
/* ??? Check if ATN (not yet implemented) is asserted and maybe
switch to PHASE_MO. */
switch (s->msg_action) {