diff options
| -rw-r--r-- | meta/recipes-devtools/qemu/qemu-0.12.4/vmware-vga-fifo-rewind.patch | 198 | ||||
| -rw-r--r-- | meta/recipes-devtools/qemu/qemu_0.12.4.bb | 3 |
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 @@ | |||
| 1 | commit 4dedc07ffbbc66002e0fd2b97d5516fe6aca5eea | ||
| 2 | Author: Andrzej Zaborowski <balrog@zabor.org> | ||
| 3 | Date: Fri Sep 10 02:23:31 2010 +0200 | ||
| 4 | |||
| 5 | vmware_vga: Add checks to deal with non-atomic fifo writes. | ||
| 6 | |||
| 7 | Janne Huttunen noticed that the FIFO end pointer is updated by the | ||
| 8 | guest after writing each word to the FIFO, at least the X.org driver | ||
| 9 | which is open does this. This means that there's no way for the | ||
| 10 | host to know if the guest is in the middle a write operation. Qemu | ||
| 11 | thus needs to read the beginning of the command up to when it's able | ||
| 12 | to tell how many words are expected for the given command. It will | ||
| 13 | abort reading and rewind the FIFO if there aren't enough words yet, | ||
| 14 | this should be relatively rare but it is suspected to have been the | ||
| 15 | cause of the occasional FIFO overrun that killed the display. | ||
| 16 | |||
| 17 | Index: qemu-0.12.4/hw/vmware_vga.c | ||
| 18 | =================================================================== | ||
| 19 | --- qemu-0.12.4.orig/hw/vmware_vga.c 2010-09-30 23:04:34.000000000 +0800 | ||
| 20 | +++ qemu-0.12.4/hw/vmware_vga.c 2010-10-01 01:17:02.000000000 +0800 | ||
| 21 | @@ -491,27 +491,37 @@ | ||
| 22 | |||
| 23 | static uint32_t last_cmd; | ||
| 24 | |||
| 25 | -static inline int vmsvga_fifo_empty(struct vmsvga_state_s *s) | ||
| 26 | +static inline int vmsvga_fifo_length(struct vmsvga_state_s *s) | ||
| 27 | { | ||
| 28 | + int num; | ||
| 29 | if (!s->config || !s->enable) | ||
| 30 | - return 1; | ||
| 31 | - return (s->cmd->next_cmd == s->cmd->stop); | ||
| 32 | + return 0; | ||
| 33 | + num = CMD(next_cmd) - CMD(stop); | ||
| 34 | + if (num < 0) | ||
| 35 | + num += CMD(max) - CMD(min); | ||
| 36 | + return num >> 2; | ||
| 37 | } | ||
| 38 | |||
| 39 | static inline uint32_t vmsvga_fifo_read_raw(struct vmsvga_state_s *s) | ||
| 40 | { | ||
| 41 | - int offset = CMD(stop); | ||
| 42 | + uint32_t cmd = s->fifo[CMD(stop) >> 2]; | ||
| 43 | |||
| 44 | + /* If parameter is not available in FIFO, return 0 rather than random | ||
| 45 | + * value. Also update the stop as missing parameter will be inserted | ||
| 46 | + * soonly, else it will be treated as new command next time. | ||
| 47 | + * With rewinding in vmsvga_fifo_run, this unlikely happen. | ||
| 48 | + */ | ||
| 49 | if (unlikely(s->cmd->next_cmd == s->cmd->stop)) { | ||
| 50 | fprintf(stderr, "%s: FIFO empty during CMD %i\n", | ||
| 51 | __FUNCTION__, last_cmd); | ||
| 52 | - return 0x00000000; | ||
| 53 | + cmd = 0; | ||
| 54 | } | ||
| 55 | |||
| 56 | - s->cmd->stop = cpu_to_le32(offset + 4); | ||
| 57 | - if (offset + 4 >= CMD(max)) | ||
| 58 | + s->cmd->stop = cpu_to_le32(CMD(stop) + 4); | ||
| 59 | + if (CMD(stop) >= CMD(max)) | ||
| 60 | s->cmd->stop = s->cmd->min; | ||
| 61 | - return s->fifo[offset >> 2]; | ||
| 62 | + | ||
| 63 | + return cmd; | ||
| 64 | } | ||
| 65 | |||
| 66 | static inline uint32_t vmsvga_fifo_read(struct vmsvga_state_s *s) | ||
| 67 | @@ -522,13 +532,23 @@ | ||
| 68 | static void vmsvga_fifo_run(struct vmsvga_state_s *s) | ||
| 69 | { | ||
| 70 | uint32_t colour; | ||
| 71 | - int args = 0; | ||
| 72 | + int args, len; | ||
| 73 | int x, y, dx, dy, width, height; | ||
| 74 | struct vmsvga_cursor_definition_s cursor; | ||
| 75 | - while (!vmsvga_fifo_empty(s)) | ||
| 76 | + uint32_t cmd_start; | ||
| 77 | + | ||
| 78 | + len = vmsvga_fifo_length(s); | ||
| 79 | + while (len > 0) { | ||
| 80 | + /* May need to go back to the start of the command if incomplete */ | ||
| 81 | + cmd_start = s->cmd->stop; | ||
| 82 | + | ||
| 83 | switch (last_cmd = vmsvga_fifo_read(s)) { | ||
| 84 | case SVGA_CMD_UPDATE: | ||
| 85 | case SVGA_CMD_UPDATE_VERBOSE: | ||
| 86 | + len -= 5; | ||
| 87 | + if (len <0) | ||
| 88 | + goto rewind; | ||
| 89 | + | ||
| 90 | x = vmsvga_fifo_read(s); | ||
| 91 | y = vmsvga_fifo_read(s); | ||
| 92 | width = vmsvga_fifo_read(s); | ||
| 93 | @@ -537,6 +557,10 @@ | ||
| 94 | break; | ||
| 95 | |||
| 96 | case SVGA_CMD_RECT_FILL: | ||
| 97 | + len -= 6; | ||
| 98 | + if (len < 0) | ||
| 99 | + goto rewind; | ||
| 100 | + | ||
| 101 | colour = vmsvga_fifo_read(s); | ||
| 102 | x = vmsvga_fifo_read(s); | ||
| 103 | y = vmsvga_fifo_read(s); | ||
| 104 | @@ -546,10 +570,15 @@ | ||
| 105 | vmsvga_fill_rect(s, colour, x, y, width, height); | ||
| 106 | break; | ||
| 107 | #else | ||
| 108 | + args = 0; | ||
| 109 | goto badcmd; | ||
| 110 | #endif | ||
| 111 | |||
| 112 | case SVGA_CMD_RECT_COPY: | ||
| 113 | + len -= 7; | ||
| 114 | + if (len < 0) | ||
| 115 | + goto rewind; | ||
| 116 | + | ||
| 117 | x = vmsvga_fifo_read(s); | ||
| 118 | y = vmsvga_fifo_read(s); | ||
| 119 | dx = vmsvga_fifo_read(s); | ||
| 120 | @@ -560,10 +589,15 @@ | ||
| 121 | vmsvga_copy_rect(s, x, y, dx, dy, width, height); | ||
| 122 | break; | ||
| 123 | #else | ||
| 124 | + args = 0; | ||
| 125 | goto badcmd; | ||
| 126 | #endif | ||
| 127 | |||
| 128 | case SVGA_CMD_DEFINE_CURSOR: | ||
| 129 | + len -= 8; | ||
| 130 | + if (len < 0) | ||
| 131 | + goto rewind; | ||
| 132 | + | ||
| 133 | cursor.id = vmsvga_fifo_read(s); | ||
| 134 | cursor.hot_x = vmsvga_fifo_read(s); | ||
| 135 | cursor.hot_y = vmsvga_fifo_read(s); | ||
| 136 | @@ -572,11 +606,14 @@ | ||
| 137 | vmsvga_fifo_read(s); | ||
| 138 | cursor.bpp = vmsvga_fifo_read(s); | ||
| 139 | |||
| 140 | + args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp); | ||
| 141 | if (SVGA_BITMAP_SIZE(x, y) > sizeof cursor.mask || | ||
| 142 | - SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) { | ||
| 143 | - args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp); | ||
| 144 | + SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) | ||
| 145 | goto badcmd; | ||
| 146 | - } | ||
| 147 | + | ||
| 148 | + len -= args; | ||
| 149 | + if (len < 0) | ||
| 150 | + goto rewind; | ||
| 151 | |||
| 152 | for (args = 0; args < SVGA_BITMAP_SIZE(x, y); args ++) | ||
| 153 | cursor.mask[args] = vmsvga_fifo_read_raw(s); | ||
| 154 | @@ -595,6 +632,10 @@ | ||
| 155 | * for so we can avoid FIFO desync if driver uses them illegally. | ||
| 156 | */ | ||
| 157 | case SVGA_CMD_DEFINE_ALPHA_CURSOR: | ||
| 158 | + len -= 6; | ||
| 159 | + if (len < 0) | ||
| 160 | + goto rewind; | ||
| 161 | + | ||
| 162 | vmsvga_fifo_read(s); | ||
| 163 | vmsvga_fifo_read(s); | ||
| 164 | vmsvga_fifo_read(s); | ||
| 165 | @@ -609,6 +650,10 @@ | ||
| 166 | args = 7; | ||
| 167 | goto badcmd; | ||
| 168 | case SVGA_CMD_DRAW_GLYPH_CLIPPED: | ||
| 169 | + len -= 4; | ||
| 170 | + if (len < 0) | ||
| 171 | + goto rewind; | ||
| 172 | + | ||
| 173 | vmsvga_fifo_read(s); | ||
| 174 | vmsvga_fifo_read(s); | ||
| 175 | args = 7 + (vmsvga_fifo_read(s) >> 2); | ||
| 176 | @@ -629,14 +674,22 @@ | ||
| 177 | break; /* Nop */ | ||
| 178 | |||
| 179 | default: | ||
| 180 | + args = 0; | ||
| 181 | badcmd: | ||
| 182 | + len -= args; | ||
| 183 | + if (len < 0) | ||
| 184 | + goto rewind; | ||
| 185 | while (args --) | ||
| 186 | vmsvga_fifo_read(s); | ||
| 187 | printf("%s: Unknown command 0x%02x in SVGA command FIFO\n", | ||
| 188 | __FUNCTION__, last_cmd); | ||
| 189 | break; | ||
| 190 | + rewind: | ||
| 191 | + s->cmd->stop = cmd_start; | ||
| 192 | + break; | ||
| 193 | } | ||
| 194 | |||
| 195 | + } | ||
| 196 | s->syncing = 0; | ||
| 197 | } | ||
| 198 | |||
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 @@ | |||
| 1 | require qemu.inc | 1 | require qemu.inc |
| 2 | 2 | ||
| 3 | PR = "r21" | 3 | PR = "r22" |
| 4 | 4 | ||
| 5 | FILESPATH = "${FILE_DIRNAME}/qemu-${PV}" | 5 | FILESPATH = "${FILE_DIRNAME}/qemu-${PV}" |
| 6 | FILESDIR = "${WORKDIR}" | 6 | FILESDIR = "${WORKDIR}" |
| @@ -20,6 +20,7 @@ SRC_URI = "\ | |||
| 20 | file://enable-i386-linux-user.patch \ | 20 | file://enable-i386-linux-user.patch \ |
| 21 | file://arm-cp15-fix.patch \ | 21 | file://arm-cp15-fix.patch \ |
| 22 | file://cursor-shadow-fix.patch \ | 22 | file://cursor-shadow-fix.patch \ |
| 23 | file://vmware-vga-fifo-rewind.patch \ | ||
| 23 | file://powerpc_rom.bin" | 24 | file://powerpc_rom.bin" |
| 24 | 25 | ||
| 25 | do_install_append () { | 26 | do_install_append () { |
