summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhai Edwin <edwin.zhai@intel.com>2010-10-01 01:43:14 +0800
committerSaul Wold <Saul.Wold@intel.com>2010-09-30 12:32:10 -0700
commit27b68f9f4c178c60e7095001a7dda3864068c6ae (patch)
treeac28ee6f19f4b196bb09a9bc627a1af10766f88d
parent7f17d12cfdcd975a777acf9fdf2b8e0ce701de05 (diff)
downloadopenembedded-core-contrib-27b68f9f4c178c60e7095001a7dda3864068c6ae.tar.gz
qemu: introduce vmware vga FIFO rewind patch to fix qemu hang
In some circumstance guest driver got interrupted before inserting all args for one command, so that qemu get an invalid args and hang. GL patch doesn't consume these missing args, which further cause FIFO disorder. This commit reverts wrong behavior of GL patch, and introduces a qemu upstream patch to rewind FIFO unpon detecting incomplete command. [BUGID #111] fixed by this. Signed-off-by: Zhai Edwin <edwin.zhai@intel.com>
-rw-r--r--meta/recipes-devtools/qemu/qemu-0.12.4/vmware-vga-fifo-rewind.patch198
-rw-r--r--meta/recipes-devtools/qemu/qemu_0.12.4.bb3
2 files changed, 200 insertions, 1 deletions
diff --git a/meta/recipes-devtools/qemu/qemu-0.12.4/vmware-vga-fifo-rewind.patch b/meta/recipes-devtools/qemu/qemu-0.12.4/vmware-vga-fifo-rewind.patch
new file mode 100644
index 0000000000..ef92f54c8b
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu-0.12.4/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.12.4/hw/vmware_vga.c
+===================================================================
+--- qemu-0.12.4.orig/hw/vmware_vga.c 2010-09-30 23:04:34.000000000 +0800
++++ qemu-0.12.4/hw/vmware_vga.c 2010-10-01 01:17:02.000000000 +0800
+@@ -491,27 +491,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)
+@@ -522,13 +532,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);
+@@ -537,6 +557,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);
+@@ -546,10 +570,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);
+@@ -560,10 +589,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);
+@@ -572,11 +606,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);
+@@ -595,6 +632,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);
+@@ -609,6 +650,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);
+@@ -629,14 +674,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;
+ }
+
diff --git a/meta/recipes-devtools/qemu/qemu_0.12.4.bb b/meta/recipes-devtools/qemu/qemu_0.12.4.bb
index 86e6561e11..6e7d86f9c6 100644
--- a/meta/recipes-devtools/qemu/qemu_0.12.4.bb
+++ b/meta/recipes-devtools/qemu/qemu_0.12.4.bb
@@ -1,6 +1,6 @@
require qemu.inc
-PR = "r21"
+PR = "r22"
FILESPATH = "${FILE_DIRNAME}/qemu-${PV}"
FILESDIR = "${WORKDIR}"
@@ -20,6 +20,7 @@ SRC_URI = "\
file://enable-i386-linux-user.patch \
file://arm-cp15-fix.patch \
file://cursor-shadow-fix.patch \
+ file://vmware-vga-fifo-rewind.patch \
file://powerpc_rom.bin"
do_install_append () {