qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Janne Huttunen <jahuttun@gmail.com>
To: andrzej zaborowski <balrogg@gmail.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] Unknown command 0xffffff in SVGA command FIFO
Date: Wed, 21 Jul 2010 19:00:10 +0300	[thread overview]
Message-ID: <4C47198A.2080308@gmail.com> (raw)
In-Reply-To: <4C470BF2.30506@gmail.com>


> Here's an experiment for sanity checking the lengths and leaving
> the command in the FIFO if it is not complete. It fixes the
> problem for me (running it right now), but I agree that it's not
> very elegant to look at :-/ .

And here's another version with couple of stupid bugs removed
(it obviously is not a good idea to busyloop if the command is
incomplete).

diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 12bff48..839f715 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -526,6 +526,17 @@ static inline int vmsvga_fifo_empty(struct vmsvga_state_s *s)
      return (s->cmd->next_cmd == s->cmd->stop);
  }

+static inline int vmsvga_fifo_items(struct vmsvga_state_s *s)
+{
+    int num;
+    if (!s->config || !s->enable)
+        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)
  {
      uint32_t cmd = s->fifo[CMD(stop) >> 2];
@@ -540,6 +551,14 @@ static inline uint32_t vmsvga_fifo_read(struct 
vmsvga_state_s *s)
      return le32_to_cpu(vmsvga_fifo_read_raw(s));
  }

+static inline uint32_t vmsvga_fifo_peek(struct vmsvga_state_s *s, uint32_t offs)
+{
+    offs = (offs << 2) + CMD(stop);
+    if (offs >= CMD(max))
+        offs = offs - CMD(max) + CMD(min);
+    return le32_to_cpu(s->fifo[offs >> 2]);
+}
+
  static void vmsvga_fifo_run(struct vmsvga_state_s *s)
  {
      uint32_t cmd, colour;
@@ -547,9 +566,12 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
      int x, y, dx, dy, width, height;
      struct vmsvga_cursor_definition_s cursor;
      while (!vmsvga_fifo_empty(s))
-        switch (cmd = vmsvga_fifo_read(s)) {
+        switch (cmd = vmsvga_fifo_peek(s, 0)) {
          case SVGA_CMD_UPDATE:
          case SVGA_CMD_UPDATE_VERBOSE:
+            if (vmsvga_fifo_items(s) < 5)
+                goto out;
+            vmsvga_fifo_read(s);
              x = vmsvga_fifo_read(s);
              y = vmsvga_fifo_read(s);
              width = vmsvga_fifo_read(s);
@@ -558,6 +580,9 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
              break;

          case SVGA_CMD_RECT_FILL:
+            if (vmsvga_fifo_items(s) < 6)
+                goto out;
+            vmsvga_fifo_read(s);
              colour = vmsvga_fifo_read(s);
              x = vmsvga_fifo_read(s);
              y = vmsvga_fifo_read(s);
@@ -571,6 +596,9 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
  #endif

          case SVGA_CMD_RECT_COPY:
+            if (vmsvga_fifo_items(s) < 7)
+                goto out;
+            vmsvga_fifo_read(s);
              x = vmsvga_fifo_read(s);
              y = vmsvga_fifo_read(s);
              dx = vmsvga_fifo_read(s);
@@ -585,13 +613,20 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
  #endif

          case SVGA_CMD_DEFINE_CURSOR:
-            cursor.id = vmsvga_fifo_read(s);
-            cursor.hot_x = vmsvga_fifo_read(s);
-            cursor.hot_y = vmsvga_fifo_read(s);
-            cursor.width = x = vmsvga_fifo_read(s);
-            cursor.height = y = vmsvga_fifo_read(s);
-            vmsvga_fifo_read(s);
-            cursor.bpp = vmsvga_fifo_read(s);
+            if (vmsvga_fifo_items(s) < 8)
+                goto out;
+            cursor.id = vmsvga_fifo_peek(s, 1);
+            cursor.hot_x = vmsvga_fifo_peek(s, 2);
+            cursor.hot_y = vmsvga_fifo_peek(s, 3);
+            cursor.width = x = vmsvga_fifo_peek(s, 4);
+            cursor.height = y = vmsvga_fifo_peek(s, 5);
+            cursor.bpp = vmsvga_fifo_peek(s, 7);
+
+            if (vmsvga_fifo_items(s) < SVGA_BITMAP_SIZE(x, y) + 
SVGA_PIXMAP_SIZE(x, y, cursor.bpp) + 8)
+                goto out;
+
+            for (args = 0; args < 8; args++)
+                vmsvga_fifo_read(s);

  	    if (SVGA_BITMAP_SIZE(x, y) > sizeof cursor.mask ||
  		SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) {
@@ -616,25 +651,43 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
           * for so we can avoid FIFO desync if driver uses them illegally.
           */
          case SVGA_CMD_DEFINE_ALPHA_CURSOR:
-            vmsvga_fifo_read(s);
-            vmsvga_fifo_read(s);
-            vmsvga_fifo_read(s);
-            x = vmsvga_fifo_read(s);
-            y = vmsvga_fifo_read(s);
+            if (vmsvga_fifo_items(s) < 6)
+                goto out;
+            x = vmsvga_fifo_peek(s, 4);
+            y = vmsvga_fifo_peek(s, 5);
+            if (vmsvga_fifo_items(s) < x * y + 6)
+                goto out;
+            for (args = 0; args < 6; args++)
+                vmsvga_fifo_read(s);
              args = x * y;
              goto badcmd;
          case SVGA_CMD_RECT_ROP_FILL:
+            if (vmsvga_fifo_items(s) < 7)
+                goto out;
+            vmsvga_fifo_read(s);
              args = 6;
              goto badcmd;
          case SVGA_CMD_RECT_ROP_COPY:
+            if (vmsvga_fifo_items(s) < 8)
+                goto out;
+            vmsvga_fifo_read(s);
              args = 7;
              goto badcmd;
          case SVGA_CMD_DRAW_GLYPH_CLIPPED:
+            if (vmsvga_fifo_items(s) < 4)
+                goto out;
+            args = 7 + (vmsvga_fifo_peek(s, 3) >> 2);
+            if (vmsvga_fifo_items(s) < args + 4)
+                goto out;
+            vmsvga_fifo_read(s);
+            vmsvga_fifo_read(s);
              vmsvga_fifo_read(s);
              vmsvga_fifo_read(s);
-            args = 7 + (vmsvga_fifo_read(s) >> 2);
              goto badcmd;
          case SVGA_CMD_SURFACE_ALPHA_BLEND:
+            if (vmsvga_fifo_items(s) < 13)
+                goto out;
+            vmsvga_fifo_read(s);
              args = 12;
              goto badcmd;

@@ -647,6 +700,7 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
          case SVGA_CMD_FRONT_ROP_FILL:
          case SVGA_CMD_FENCE:
          case SVGA_CMD_INVALID_CMD:
+            vmsvga_fifo_read(s);
              break; /* Nop */

          default:
@@ -658,6 +712,7 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
              break;
          }

+out:
      s->syncing = 0;
  }

  reply	other threads:[~2010-07-21 16:00 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-21 11:17 [Qemu-devel] Unknown command 0xffffff in SVGA command FIFO Janne Huttunen
2010-07-21 11:45 ` andrzej zaborowski
2010-07-21 12:14   ` Janne Huttunen
2010-07-21 12:33     ` andrzej zaborowski
2010-07-21 15:02       ` Janne Huttunen
2010-07-21 16:00         ` Janne Huttunen [this message]
2010-07-23  1:35           ` balrog
2010-08-16 20:26             ` Janne Huttunen
2010-09-10  1:34               ` andrzej zaborowski
     [not found]           ` <4080236889252115527@unknownmsgid>
2010-07-23  1:41             ` andrzej zaborowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4C47198A.2080308@gmail.com \
    --to=jahuttun@gmail.com \
    --cc=balrogg@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).