summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/qemu/qemu-0.13.0/vmware-vga-fifo-rewind.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/qemu/qemu-0.13.0/vmware-vga-fifo-rewind.patch')
-rw-r--r--meta/recipes-devtools/qemu/qemu-0.13.0/vmware-vga-fifo-rewind.patch198
1 files changed, 198 insertions, 0 deletions
diff --git a/meta/recipes-devtools/qemu/qemu-0.13.0/vmware-vga-fifo-rewind.patch b/meta/recipes-devtools/qemu/qemu-0.13.0/vmware-vga-fifo-rewind.patch
new file mode 100644
index 0000000..867e54b
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu-0.13.0/vmware-vga-fifo-rewind.patch
@@ -0,0 +1,198 @@
+commit 4dedc07ffbbc66002e0fd2b97d5516fe6aca5eea
+Author: Andrzej Zaborowski <balrog@zabor.org>
+Date: Fri Sep 10 02:23:31 2010 +0200
+
+ vmware_vga: Add checks to deal with non-atomic fifo writes.
+
+ Janne Huttunen noticed that the FIFO end pointer is updated by the
+ guest after writing each word to the FIFO, at least the X.org driver
+ which is open does this. This means that there's no way for the
+ host to know if the guest is in the middle a write operation. Qemu
+ thus needs to read the beginning of the command up to when it's able
+ to tell how many words are expected for the given command. It will
+ abort reading and rewind the FIFO if there aren't enough words yet,
+ this should be relatively rare but it is suspected to have been the
+ cause of the occasional FIFO overrun that killed the display.
+
+Index: qemu-0.13.0/hw/vmware_vga.c
+===================================================================
+--- qemu-0.13.0.orig/hw/vmware_vga.c 2011-01-15 18:06:06.000000000 +0800
++++ qemu-0.13.0/hw/vmware_vga.c 2011-01-15 18:17:04.000000000 +0800
+@@ -521,27 +521,37 @@
+
+ static uint32_t last_cmd;
+
+-static inline int vmsvga_fifo_empty(struct vmsvga_state_s *s)
++static inline int vmsvga_fifo_length(struct vmsvga_state_s *s)
+ {
++ int num;
+ if (!s->config || !s->enable)
+- return 1;
+- return (s->cmd->next_cmd == s->cmd->stop);
++ return 0;
++ num = CMD(next_cmd) - CMD(stop);
++ if (num < 0)
++ num += CMD(max) - CMD(min);
++ return num >> 2;
+ }
+
+ static inline uint32_t vmsvga_fifo_read_raw(struct vmsvga_state_s *s)
+ {
+- int offset = CMD(stop);
++ uint32_t cmd = s->fifo[CMD(stop) >> 2];
+
++ /* If parameter is not available in FIFO, return 0 rather than random
++ * value. Also update the stop as missing parameter will be inserted
++ * soonly, else it will be treated as new command next time.
++ * With rewinding in vmsvga_fifo_run, this unlikely happen.
++ */
+ if (unlikely(s->cmd->next_cmd == s->cmd->stop)) {
+ fprintf(stderr, "%s: FIFO empty during CMD %i\n",
+ __FUNCTION__, last_cmd);
+- return 0x00000000;
++ cmd = 0;
+ }
+
+- s->cmd->stop = cpu_to_le32(offset + 4);
+- if (offset + 4 >= CMD(max))
++ s->cmd->stop = cpu_to_le32(CMD(stop) + 4);
++ if (CMD(stop) >= CMD(max))
+ s->cmd->stop = s->cmd->min;
+- return s->fifo[offset >> 2];
++
++ return cmd;
+ }
+
+ static inline uint32_t vmsvga_fifo_read(struct vmsvga_state_s *s)
+@@ -552,13 +562,23 @@
+ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
+ {
+ uint32_t colour;
+- int args = 0;
++ int args, len;
+ int x, y, dx, dy, width, height;
+ struct vmsvga_cursor_definition_s cursor;
+- while (!vmsvga_fifo_empty(s))
++ uint32_t cmd_start;
++
++ len = vmsvga_fifo_length(s);
++ while (len > 0) {
++ /* May need to go back to the start of the command if incomplete */
++ cmd_start = s->cmd->stop;
++
+ switch (last_cmd = vmsvga_fifo_read(s)) {
+ case SVGA_CMD_UPDATE:
+ case SVGA_CMD_UPDATE_VERBOSE:
++ len -= 5;
++ if (len <0)
++ goto rewind;
++
+ x = vmsvga_fifo_read(s);
+ y = vmsvga_fifo_read(s);
+ width = vmsvga_fifo_read(s);
+@@ -567,6 +587,10 @@
+ break;
+
+ case SVGA_CMD_RECT_FILL:
++ len -= 6;
++ if (len < 0)
++ goto rewind;
++
+ colour = vmsvga_fifo_read(s);
+ x = vmsvga_fifo_read(s);
+ y = vmsvga_fifo_read(s);
+@@ -576,10 +600,15 @@
+ vmsvga_fill_rect(s, colour, x, y, width, height);
+ break;
+ #else
++ args = 0;
+ goto badcmd;
+ #endif
+
+ case SVGA_CMD_RECT_COPY:
++ len -= 7;
++ if (len < 0)
++ goto rewind;
++
+ x = vmsvga_fifo_read(s);
+ y = vmsvga_fifo_read(s);
+ dx = vmsvga_fifo_read(s);
+@@ -590,10 +619,15 @@
+ vmsvga_copy_rect(s, x, y, dx, dy, width, height);
+ break;
+ #else
++ args = 0;
+ goto badcmd;
+ #endif
+
+ case SVGA_CMD_DEFINE_CURSOR:
++ len -= 8;
++ if (len < 0)
++ goto rewind;
++
+ cursor.id = vmsvga_fifo_read(s);
+ cursor.hot_x = vmsvga_fifo_read(s);
+ cursor.hot_y = vmsvga_fifo_read(s);
+@@ -602,11 +636,14 @@
+ vmsvga_fifo_read(s);
+ cursor.bpp = vmsvga_fifo_read(s);
+
++ args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp);
+ if (SVGA_BITMAP_SIZE(x, y) > sizeof cursor.mask ||
+- SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) {
+- args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp);
++ SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image)
+ goto badcmd;
+- }
++
++ len -= args;
++ if (len < 0)
++ goto rewind;
+
+ for (args = 0; args < SVGA_BITMAP_SIZE(x, y); args ++)
+ cursor.mask[args] = vmsvga_fifo_read_raw(s);
+@@ -625,6 +662,10 @@
+ * for so we can avoid FIFO desync if driver uses them illegally.
+ */
+ case SVGA_CMD_DEFINE_ALPHA_CURSOR:
++ len -= 6;
++ if (len < 0)
++ goto rewind;
++
+ vmsvga_fifo_read(s);
+ vmsvga_fifo_read(s);
+ vmsvga_fifo_read(s);
+@@ -639,6 +680,10 @@
+ args = 7;
+ goto badcmd;
+ case SVGA_CMD_DRAW_GLYPH_CLIPPED:
++ len -= 4;
++ if (len < 0)
++ goto rewind;
++
+ vmsvga_fifo_read(s);
+ vmsvga_fifo_read(s);
+ args = 7 + (vmsvga_fifo_read(s) >> 2);
+@@ -659,14 +704,22 @@
+ break; /* Nop */
+
+ default:
++ args = 0;
+ badcmd:
++ len -= args;
++ if (len < 0)
++ goto rewind;
+ while (args --)
+ vmsvga_fifo_read(s);
+ printf("%s: Unknown command 0x%02x in SVGA command FIFO\n",
+ __FUNCTION__, last_cmd);
+ break;
++ rewind:
++ s->cmd->stop = cmd_start;
++ break;
+ }
+
++ }
+ s->syncing = 0;
+ }
+
OpenPOWER on IntegriCloud