1 /* 2 * Copyright (C) 2010 Red Hat, Inc. 3 * 4 * written by Yaniv Kamay, Izik Eidus, Gerd Hoffmann 5 * maintained by Gerd Hoffmann <kraxel@redhat.com> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 or 10 * (at your option) version 3 of the License. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "qemu/osdep.h" 22 #include <zlib.h> 23 24 #include "qemu-common.h" 25 #include "qemu/timer.h" 26 #include "qemu/queue.h" 27 #include "qemu/atomic.h" 28 #include "sysemu/sysemu.h" 29 #include "trace.h" 30 31 #include "qxl.h" 32 33 /* 34 * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as 35 * such can be changed by the guest, so to avoid a guest trigerrable 36 * abort we just qxl_set_guest_bug and set the return to NULL. Still 37 * it may happen as a result of emulator bug as well. 38 */ 39 #undef SPICE_RING_PROD_ITEM 40 #define SPICE_RING_PROD_ITEM(qxl, r, ret) { \ 41 uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \ 42 if (prod >= ARRAY_SIZE((r)->items)) { \ 43 qxl_set_guest_bug(qxl, "SPICE_RING_PROD_ITEM indices mismatch " \ 44 "%u >= %zu", prod, ARRAY_SIZE((r)->items)); \ 45 ret = NULL; \ 46 } else { \ 47 ret = &(r)->items[prod].el; \ 48 } \ 49 } 50 51 #undef SPICE_RING_CONS_ITEM 52 #define SPICE_RING_CONS_ITEM(qxl, r, ret) { \ 53 uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \ 54 if (cons >= ARRAY_SIZE((r)->items)) { \ 55 qxl_set_guest_bug(qxl, "SPICE_RING_CONS_ITEM indices mismatch " \ 56 "%u >= %zu", cons, ARRAY_SIZE((r)->items)); \ 57 ret = NULL; \ 58 } else { \ 59 ret = &(r)->items[cons].el; \ 60 } \ 61 } 62 63 #undef ALIGN 64 #define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1)) 65 66 #define PIXEL_SIZE 0.2936875 //1280x1024 is 14.8" x 11.9" 67 68 #define QXL_MODE(_x, _y, _b, _o) \ 69 { .x_res = _x, \ 70 .y_res = _y, \ 71 .bits = _b, \ 72 .stride = (_x) * (_b) / 8, \ 73 .x_mili = PIXEL_SIZE * (_x), \ 74 .y_mili = PIXEL_SIZE * (_y), \ 75 .orientation = _o, \ 76 } 77 78 #define QXL_MODE_16_32(x_res, y_res, orientation) \ 79 QXL_MODE(x_res, y_res, 16, orientation), \ 80 QXL_MODE(x_res, y_res, 32, orientation) 81 82 #define QXL_MODE_EX(x_res, y_res) \ 83 QXL_MODE_16_32(x_res, y_res, 0), \ 84 QXL_MODE_16_32(x_res, y_res, 1) 85 86 static QXLMode qxl_modes[] = { 87 QXL_MODE_EX(640, 480), 88 QXL_MODE_EX(800, 480), 89 QXL_MODE_EX(800, 600), 90 QXL_MODE_EX(832, 624), 91 QXL_MODE_EX(960, 640), 92 QXL_MODE_EX(1024, 600), 93 QXL_MODE_EX(1024, 768), 94 QXL_MODE_EX(1152, 864), 95 QXL_MODE_EX(1152, 870), 96 QXL_MODE_EX(1280, 720), 97 QXL_MODE_EX(1280, 760), 98 QXL_MODE_EX(1280, 768), 99 QXL_MODE_EX(1280, 800), 100 QXL_MODE_EX(1280, 960), 101 QXL_MODE_EX(1280, 1024), 102 QXL_MODE_EX(1360, 768), 103 QXL_MODE_EX(1366, 768), 104 QXL_MODE_EX(1400, 1050), 105 QXL_MODE_EX(1440, 900), 106 QXL_MODE_EX(1600, 900), 107 QXL_MODE_EX(1600, 1200), 108 QXL_MODE_EX(1680, 1050), 109 QXL_MODE_EX(1920, 1080), 110 /* these modes need more than 8 MB video memory */ 111 QXL_MODE_EX(1920, 1200), 112 QXL_MODE_EX(1920, 1440), 113 QXL_MODE_EX(2000, 2000), 114 QXL_MODE_EX(2048, 1536), 115 QXL_MODE_EX(2048, 2048), 116 QXL_MODE_EX(2560, 1440), 117 QXL_MODE_EX(2560, 1600), 118 /* these modes need more than 16 MB video memory */ 119 QXL_MODE_EX(2560, 2048), 120 QXL_MODE_EX(2800, 2100), 121 QXL_MODE_EX(3200, 2400), 122 /* these modes need more than 32 MB video memory */ 123 QXL_MODE_EX(3840, 2160), /* 4k mainstream */ 124 QXL_MODE_EX(4096, 2160), /* 4k */ 125 /* these modes need more than 64 MB video memory */ 126 QXL_MODE_EX(7680, 4320), /* 8k mainstream */ 127 /* these modes need more than 128 MB video memory */ 128 QXL_MODE_EX(8192, 4320), /* 8k */ 129 }; 130 131 static void qxl_send_events(PCIQXLDevice *d, uint32_t events); 132 static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async); 133 static void qxl_reset_memslots(PCIQXLDevice *d); 134 static void qxl_reset_surfaces(PCIQXLDevice *d); 135 static void qxl_ring_set_dirty(PCIQXLDevice *qxl); 136 137 static void qxl_hw_update(void *opaque); 138 139 void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) 140 { 141 trace_qxl_set_guest_bug(qxl->id); 142 qxl_send_events(qxl, QXL_INTERRUPT_ERROR); 143 qxl->guest_bug = 1; 144 if (qxl->guestdebug) { 145 va_list ap; 146 va_start(ap, msg); 147 fprintf(stderr, "qxl-%d: guest bug: ", qxl->id); 148 vfprintf(stderr, msg, ap); 149 fprintf(stderr, "\n"); 150 va_end(ap); 151 } 152 } 153 154 static void qxl_clear_guest_bug(PCIQXLDevice *qxl) 155 { 156 qxl->guest_bug = 0; 157 } 158 159 void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, 160 struct QXLRect *area, struct QXLRect *dirty_rects, 161 uint32_t num_dirty_rects, 162 uint32_t clear_dirty_region, 163 qxl_async_io async, struct QXLCookie *cookie) 164 { 165 trace_qxl_spice_update_area(qxl->id, surface_id, area->left, area->right, 166 area->top, area->bottom); 167 trace_qxl_spice_update_area_rest(qxl->id, num_dirty_rects, 168 clear_dirty_region); 169 if (async == QXL_SYNC) { 170 spice_qxl_update_area(&qxl->ssd.qxl, surface_id, area, 171 dirty_rects, num_dirty_rects, clear_dirty_region); 172 } else { 173 assert(cookie != NULL); 174 spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area, 175 clear_dirty_region, (uintptr_t)cookie); 176 } 177 } 178 179 static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl, 180 uint32_t id) 181 { 182 trace_qxl_spice_destroy_surface_wait_complete(qxl->id, id); 183 qemu_mutex_lock(&qxl->track_lock); 184 qxl->guest_surfaces.cmds[id] = 0; 185 qxl->guest_surfaces.count--; 186 qemu_mutex_unlock(&qxl->track_lock); 187 } 188 189 static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id, 190 qxl_async_io async) 191 { 192 QXLCookie *cookie; 193 194 trace_qxl_spice_destroy_surface_wait(qxl->id, id, async); 195 if (async) { 196 cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO, 197 QXL_IO_DESTROY_SURFACE_ASYNC); 198 cookie->u.surface_id = id; 199 spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uintptr_t)cookie); 200 } else { 201 spice_qxl_destroy_surface_wait(&qxl->ssd.qxl, id); 202 qxl_spice_destroy_surface_wait_complete(qxl, id); 203 } 204 } 205 206 static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl) 207 { 208 trace_qxl_spice_flush_surfaces_async(qxl->id, qxl->guest_surfaces.count, 209 qxl->num_free_res); 210 spice_qxl_flush_surfaces_async(&qxl->ssd.qxl, 211 (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, 212 QXL_IO_FLUSH_SURFACES_ASYNC)); 213 } 214 215 void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, 216 uint32_t count) 217 { 218 trace_qxl_spice_loadvm_commands(qxl->id, ext, count); 219 spice_qxl_loadvm_commands(&qxl->ssd.qxl, ext, count); 220 } 221 222 void qxl_spice_oom(PCIQXLDevice *qxl) 223 { 224 trace_qxl_spice_oom(qxl->id); 225 spice_qxl_oom(&qxl->ssd.qxl); 226 } 227 228 void qxl_spice_reset_memslots(PCIQXLDevice *qxl) 229 { 230 trace_qxl_spice_reset_memslots(qxl->id); 231 spice_qxl_reset_memslots(&qxl->ssd.qxl); 232 } 233 234 static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl) 235 { 236 trace_qxl_spice_destroy_surfaces_complete(qxl->id); 237 qemu_mutex_lock(&qxl->track_lock); 238 memset(qxl->guest_surfaces.cmds, 0, 239 sizeof(qxl->guest_surfaces.cmds[0]) * qxl->ssd.num_surfaces); 240 qxl->guest_surfaces.count = 0; 241 qemu_mutex_unlock(&qxl->track_lock); 242 } 243 244 static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async) 245 { 246 trace_qxl_spice_destroy_surfaces(qxl->id, async); 247 if (async) { 248 spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl, 249 (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, 250 QXL_IO_DESTROY_ALL_SURFACES_ASYNC)); 251 } else { 252 spice_qxl_destroy_surfaces(&qxl->ssd.qxl); 253 qxl_spice_destroy_surfaces_complete(qxl); 254 } 255 } 256 257 static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay) 258 { 259 trace_qxl_spice_monitors_config(qxl->id); 260 if (replay) { 261 /* 262 * don't use QXL_COOKIE_TYPE_IO: 263 * - we are not running yet (post_load), we will assert 264 * in send_events 265 * - this is not a guest io, but a reply, so async_io isn't set. 266 */ 267 spice_qxl_monitors_config_async(&qxl->ssd.qxl, 268 qxl->guest_monitors_config, 269 MEMSLOT_GROUP_GUEST, 270 (uintptr_t)qxl_cookie_new( 271 QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG, 272 0)); 273 } else { 274 #if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */ 275 if (qxl->max_outputs) { 276 spice_qxl_set_max_monitors(&qxl->ssd.qxl, qxl->max_outputs); 277 } 278 #endif 279 qxl->guest_monitors_config = qxl->ram->monitors_config; 280 spice_qxl_monitors_config_async(&qxl->ssd.qxl, 281 qxl->ram->monitors_config, 282 MEMSLOT_GROUP_GUEST, 283 (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, 284 QXL_IO_MONITORS_CONFIG_ASYNC)); 285 } 286 } 287 288 void qxl_spice_reset_image_cache(PCIQXLDevice *qxl) 289 { 290 trace_qxl_spice_reset_image_cache(qxl->id); 291 spice_qxl_reset_image_cache(&qxl->ssd.qxl); 292 } 293 294 void qxl_spice_reset_cursor(PCIQXLDevice *qxl) 295 { 296 trace_qxl_spice_reset_cursor(qxl->id); 297 spice_qxl_reset_cursor(&qxl->ssd.qxl); 298 qemu_mutex_lock(&qxl->track_lock); 299 qxl->guest_cursor = 0; 300 qemu_mutex_unlock(&qxl->track_lock); 301 if (qxl->ssd.cursor) { 302 cursor_put(qxl->ssd.cursor); 303 } 304 qxl->ssd.cursor = cursor_builtin_hidden(); 305 } 306 307 static ram_addr_t qxl_rom_size(void) 308 { 309 #define QXL_REQUIRED_SZ (sizeof(QXLRom) + sizeof(QXLModes) + sizeof(qxl_modes)) 310 #define QXL_ROM_SZ 8192 311 312 QEMU_BUILD_BUG_ON(QXL_REQUIRED_SZ > QXL_ROM_SZ); 313 return QXL_ROM_SZ; 314 } 315 316 static void init_qxl_rom(PCIQXLDevice *d) 317 { 318 QXLRom *rom = memory_region_get_ram_ptr(&d->rom_bar); 319 QXLModes *modes = (QXLModes *)(rom + 1); 320 uint32_t ram_header_size; 321 uint32_t surface0_area_size; 322 uint32_t num_pages; 323 uint32_t fb; 324 int i, n; 325 326 memset(rom, 0, d->rom_size); 327 328 rom->magic = cpu_to_le32(QXL_ROM_MAGIC); 329 rom->id = cpu_to_le32(d->id); 330 rom->log_level = cpu_to_le32(d->guestdebug); 331 rom->modes_offset = cpu_to_le32(sizeof(QXLRom)); 332 333 rom->slot_gen_bits = MEMSLOT_GENERATION_BITS; 334 rom->slot_id_bits = MEMSLOT_SLOT_BITS; 335 rom->slots_start = 1; 336 rom->slots_end = NUM_MEMSLOTS - 1; 337 rom->n_surfaces = cpu_to_le32(d->ssd.num_surfaces); 338 339 for (i = 0, n = 0; i < ARRAY_SIZE(qxl_modes); i++) { 340 fb = qxl_modes[i].y_res * qxl_modes[i].stride; 341 if (fb > d->vgamem_size) { 342 continue; 343 } 344 modes->modes[n].id = cpu_to_le32(i); 345 modes->modes[n].x_res = cpu_to_le32(qxl_modes[i].x_res); 346 modes->modes[n].y_res = cpu_to_le32(qxl_modes[i].y_res); 347 modes->modes[n].bits = cpu_to_le32(qxl_modes[i].bits); 348 modes->modes[n].stride = cpu_to_le32(qxl_modes[i].stride); 349 modes->modes[n].x_mili = cpu_to_le32(qxl_modes[i].x_mili); 350 modes->modes[n].y_mili = cpu_to_le32(qxl_modes[i].y_mili); 351 modes->modes[n].orientation = cpu_to_le32(qxl_modes[i].orientation); 352 n++; 353 } 354 modes->n_modes = cpu_to_le32(n); 355 356 ram_header_size = ALIGN(sizeof(QXLRam), 4096); 357 surface0_area_size = ALIGN(d->vgamem_size, 4096); 358 num_pages = d->vga.vram_size; 359 num_pages -= ram_header_size; 360 num_pages -= surface0_area_size; 361 num_pages = num_pages / QXL_PAGE_SIZE; 362 363 assert(ram_header_size + surface0_area_size <= d->vga.vram_size); 364 365 rom->draw_area_offset = cpu_to_le32(0); 366 rom->surface0_area_size = cpu_to_le32(surface0_area_size); 367 rom->pages_offset = cpu_to_le32(surface0_area_size); 368 rom->num_pages = cpu_to_le32(num_pages); 369 rom->ram_header_offset = cpu_to_le32(d->vga.vram_size - ram_header_size); 370 371 d->shadow_rom = *rom; 372 d->rom = rom; 373 d->modes = modes; 374 } 375 376 static void init_qxl_ram(PCIQXLDevice *d) 377 { 378 uint8_t *buf; 379 uint64_t *item; 380 381 buf = d->vga.vram_ptr; 382 d->ram = (QXLRam *)(buf + le32_to_cpu(d->shadow_rom.ram_header_offset)); 383 d->ram->magic = cpu_to_le32(QXL_RAM_MAGIC); 384 d->ram->int_pending = cpu_to_le32(0); 385 d->ram->int_mask = cpu_to_le32(0); 386 d->ram->update_surface = 0; 387 d->ram->monitors_config = 0; 388 SPICE_RING_INIT(&d->ram->cmd_ring); 389 SPICE_RING_INIT(&d->ram->cursor_ring); 390 SPICE_RING_INIT(&d->ram->release_ring); 391 SPICE_RING_PROD_ITEM(d, &d->ram->release_ring, item); 392 assert(item); 393 *item = 0; 394 qxl_ring_set_dirty(d); 395 } 396 397 /* can be called from spice server thread context */ 398 static void qxl_set_dirty(MemoryRegion *mr, ram_addr_t addr, ram_addr_t end) 399 { 400 memory_region_set_dirty(mr, addr, end - addr); 401 } 402 403 static void qxl_rom_set_dirty(PCIQXLDevice *qxl) 404 { 405 qxl_set_dirty(&qxl->rom_bar, 0, qxl->rom_size); 406 } 407 408 /* called from spice server thread context only */ 409 static void qxl_ram_set_dirty(PCIQXLDevice *qxl, void *ptr) 410 { 411 void *base = qxl->vga.vram_ptr; 412 intptr_t offset; 413 414 offset = ptr - base; 415 assert(offset < qxl->vga.vram_size); 416 qxl_set_dirty(&qxl->vga.vram, offset, offset + 3); 417 } 418 419 /* can be called from spice server thread context */ 420 static void qxl_ring_set_dirty(PCIQXLDevice *qxl) 421 { 422 ram_addr_t addr = qxl->shadow_rom.ram_header_offset; 423 ram_addr_t end = qxl->vga.vram_size; 424 qxl_set_dirty(&qxl->vga.vram, addr, end); 425 } 426 427 /* 428 * keep track of some command state, for savevm/loadvm. 429 * called from spice server thread context only 430 */ 431 static int qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) 432 { 433 switch (le32_to_cpu(ext->cmd.type)) { 434 case QXL_CMD_SURFACE: 435 { 436 QXLSurfaceCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); 437 438 if (!cmd) { 439 return 1; 440 } 441 uint32_t id = le32_to_cpu(cmd->surface_id); 442 443 if (id >= qxl->ssd.num_surfaces) { 444 qxl_set_guest_bug(qxl, "QXL_CMD_SURFACE id %d >= %d", id, 445 qxl->ssd.num_surfaces); 446 return 1; 447 } 448 if (cmd->type == QXL_SURFACE_CMD_CREATE && 449 (cmd->u.surface_create.stride & 0x03) != 0) { 450 qxl_set_guest_bug(qxl, "QXL_CMD_SURFACE stride = %d %% 4 != 0\n", 451 cmd->u.surface_create.stride); 452 return 1; 453 } 454 qemu_mutex_lock(&qxl->track_lock); 455 if (cmd->type == QXL_SURFACE_CMD_CREATE) { 456 qxl->guest_surfaces.cmds[id] = ext->cmd.data; 457 qxl->guest_surfaces.count++; 458 if (qxl->guest_surfaces.max < qxl->guest_surfaces.count) 459 qxl->guest_surfaces.max = qxl->guest_surfaces.count; 460 } 461 if (cmd->type == QXL_SURFACE_CMD_DESTROY) { 462 qxl->guest_surfaces.cmds[id] = 0; 463 qxl->guest_surfaces.count--; 464 } 465 qemu_mutex_unlock(&qxl->track_lock); 466 break; 467 } 468 case QXL_CMD_CURSOR: 469 { 470 QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); 471 472 if (!cmd) { 473 return 1; 474 } 475 if (cmd->type == QXL_CURSOR_SET) { 476 qemu_mutex_lock(&qxl->track_lock); 477 qxl->guest_cursor = ext->cmd.data; 478 qemu_mutex_unlock(&qxl->track_lock); 479 } 480 if (cmd->type == QXL_CURSOR_HIDE) { 481 qemu_mutex_lock(&qxl->track_lock); 482 qxl->guest_cursor = 0; 483 qemu_mutex_unlock(&qxl->track_lock); 484 } 485 break; 486 } 487 } 488 return 0; 489 } 490 491 /* spice display interface callbacks */ 492 493 static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker) 494 { 495 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 496 497 trace_qxl_interface_attach_worker(qxl->id); 498 qxl->ssd.worker = qxl_worker; 499 } 500 501 static void interface_set_compression_level(QXLInstance *sin, int level) 502 { 503 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 504 505 trace_qxl_interface_set_compression_level(qxl->id, level); 506 qxl->shadow_rom.compression_level = cpu_to_le32(level); 507 qxl->rom->compression_level = cpu_to_le32(level); 508 qxl_rom_set_dirty(qxl); 509 } 510 511 #if SPICE_NEEDS_SET_MM_TIME 512 static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time) 513 { 514 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 515 516 if (!qemu_spice_display_is_running(&qxl->ssd)) { 517 return; 518 } 519 520 trace_qxl_interface_set_mm_time(qxl->id, mm_time); 521 qxl->shadow_rom.mm_clock = cpu_to_le32(mm_time); 522 qxl->rom->mm_clock = cpu_to_le32(mm_time); 523 qxl_rom_set_dirty(qxl); 524 } 525 #endif 526 527 static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info) 528 { 529 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 530 531 trace_qxl_interface_get_init_info(qxl->id); 532 info->memslot_gen_bits = MEMSLOT_GENERATION_BITS; 533 info->memslot_id_bits = MEMSLOT_SLOT_BITS; 534 info->num_memslots = NUM_MEMSLOTS; 535 info->num_memslots_groups = NUM_MEMSLOTS_GROUPS; 536 info->internal_groupslot_id = 0; 537 info->qxl_ram_size = 538 le32_to_cpu(qxl->shadow_rom.num_pages) << QXL_PAGE_BITS; 539 info->n_surfaces = qxl->ssd.num_surfaces; 540 } 541 542 static const char *qxl_mode_to_string(int mode) 543 { 544 switch (mode) { 545 case QXL_MODE_COMPAT: 546 return "compat"; 547 case QXL_MODE_NATIVE: 548 return "native"; 549 case QXL_MODE_UNDEFINED: 550 return "undefined"; 551 case QXL_MODE_VGA: 552 return "vga"; 553 } 554 return "INVALID"; 555 } 556 557 static const char *io_port_to_string(uint32_t io_port) 558 { 559 if (io_port >= QXL_IO_RANGE_SIZE) { 560 return "out of range"; 561 } 562 static const char *io_port_to_string[QXL_IO_RANGE_SIZE + 1] = { 563 [QXL_IO_NOTIFY_CMD] = "QXL_IO_NOTIFY_CMD", 564 [QXL_IO_NOTIFY_CURSOR] = "QXL_IO_NOTIFY_CURSOR", 565 [QXL_IO_UPDATE_AREA] = "QXL_IO_UPDATE_AREA", 566 [QXL_IO_UPDATE_IRQ] = "QXL_IO_UPDATE_IRQ", 567 [QXL_IO_NOTIFY_OOM] = "QXL_IO_NOTIFY_OOM", 568 [QXL_IO_RESET] = "QXL_IO_RESET", 569 [QXL_IO_SET_MODE] = "QXL_IO_SET_MODE", 570 [QXL_IO_LOG] = "QXL_IO_LOG", 571 [QXL_IO_MEMSLOT_ADD] = "QXL_IO_MEMSLOT_ADD", 572 [QXL_IO_MEMSLOT_DEL] = "QXL_IO_MEMSLOT_DEL", 573 [QXL_IO_DETACH_PRIMARY] = "QXL_IO_DETACH_PRIMARY", 574 [QXL_IO_ATTACH_PRIMARY] = "QXL_IO_ATTACH_PRIMARY", 575 [QXL_IO_CREATE_PRIMARY] = "QXL_IO_CREATE_PRIMARY", 576 [QXL_IO_DESTROY_PRIMARY] = "QXL_IO_DESTROY_PRIMARY", 577 [QXL_IO_DESTROY_SURFACE_WAIT] = "QXL_IO_DESTROY_SURFACE_WAIT", 578 [QXL_IO_DESTROY_ALL_SURFACES] = "QXL_IO_DESTROY_ALL_SURFACES", 579 [QXL_IO_UPDATE_AREA_ASYNC] = "QXL_IO_UPDATE_AREA_ASYNC", 580 [QXL_IO_MEMSLOT_ADD_ASYNC] = "QXL_IO_MEMSLOT_ADD_ASYNC", 581 [QXL_IO_CREATE_PRIMARY_ASYNC] = "QXL_IO_CREATE_PRIMARY_ASYNC", 582 [QXL_IO_DESTROY_PRIMARY_ASYNC] = "QXL_IO_DESTROY_PRIMARY_ASYNC", 583 [QXL_IO_DESTROY_SURFACE_ASYNC] = "QXL_IO_DESTROY_SURFACE_ASYNC", 584 [QXL_IO_DESTROY_ALL_SURFACES_ASYNC] 585 = "QXL_IO_DESTROY_ALL_SURFACES_ASYNC", 586 [QXL_IO_FLUSH_SURFACES_ASYNC] = "QXL_IO_FLUSH_SURFACES_ASYNC", 587 [QXL_IO_FLUSH_RELEASE] = "QXL_IO_FLUSH_RELEASE", 588 [QXL_IO_MONITORS_CONFIG_ASYNC] = "QXL_IO_MONITORS_CONFIG_ASYNC", 589 }; 590 return io_port_to_string[io_port]; 591 } 592 593 /* called from spice server thread context only */ 594 static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) 595 { 596 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 597 SimpleSpiceUpdate *update; 598 QXLCommandRing *ring; 599 QXLCommand *cmd; 600 int notify, ret; 601 602 trace_qxl_ring_command_check(qxl->id, qxl_mode_to_string(qxl->mode)); 603 604 switch (qxl->mode) { 605 case QXL_MODE_VGA: 606 ret = false; 607 qemu_mutex_lock(&qxl->ssd.lock); 608 update = QTAILQ_FIRST(&qxl->ssd.updates); 609 if (update != NULL) { 610 QTAILQ_REMOVE(&qxl->ssd.updates, update, next); 611 *ext = update->ext; 612 ret = true; 613 } 614 qemu_mutex_unlock(&qxl->ssd.lock); 615 if (ret) { 616 trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode)); 617 qxl_log_command(qxl, "vga", ext); 618 } 619 return ret; 620 case QXL_MODE_COMPAT: 621 case QXL_MODE_NATIVE: 622 case QXL_MODE_UNDEFINED: 623 ring = &qxl->ram->cmd_ring; 624 if (qxl->guest_bug || SPICE_RING_IS_EMPTY(ring)) { 625 return false; 626 } 627 SPICE_RING_CONS_ITEM(qxl, ring, cmd); 628 if (!cmd) { 629 return false; 630 } 631 ext->cmd = *cmd; 632 ext->group_id = MEMSLOT_GROUP_GUEST; 633 ext->flags = qxl->cmdflags; 634 SPICE_RING_POP(ring, notify); 635 qxl_ring_set_dirty(qxl); 636 if (notify) { 637 qxl_send_events(qxl, QXL_INTERRUPT_DISPLAY); 638 } 639 qxl->guest_primary.commands++; 640 qxl_track_command(qxl, ext); 641 qxl_log_command(qxl, "cmd", ext); 642 trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode)); 643 return true; 644 default: 645 return false; 646 } 647 } 648 649 /* called from spice server thread context only */ 650 static int interface_req_cmd_notification(QXLInstance *sin) 651 { 652 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 653 int wait = 1; 654 655 trace_qxl_ring_command_req_notification(qxl->id); 656 switch (qxl->mode) { 657 case QXL_MODE_COMPAT: 658 case QXL_MODE_NATIVE: 659 case QXL_MODE_UNDEFINED: 660 SPICE_RING_CONS_WAIT(&qxl->ram->cmd_ring, wait); 661 qxl_ring_set_dirty(qxl); 662 break; 663 default: 664 /* nothing */ 665 break; 666 } 667 return wait; 668 } 669 670 /* called from spice server thread context only */ 671 static inline void qxl_push_free_res(PCIQXLDevice *d, int flush) 672 { 673 QXLReleaseRing *ring = &d->ram->release_ring; 674 uint64_t *item; 675 int notify; 676 677 #define QXL_FREE_BUNCH_SIZE 32 678 679 if (ring->prod - ring->cons + 1 == ring->num_items) { 680 /* ring full -- can't push */ 681 return; 682 } 683 if (!flush && d->oom_running) { 684 /* collect everything from oom handler before pushing */ 685 return; 686 } 687 if (!flush && d->num_free_res < QXL_FREE_BUNCH_SIZE) { 688 /* collect a bit more before pushing */ 689 return; 690 } 691 692 SPICE_RING_PUSH(ring, notify); 693 trace_qxl_ring_res_push(d->id, qxl_mode_to_string(d->mode), 694 d->guest_surfaces.count, d->num_free_res, 695 d->last_release, notify ? "yes" : "no"); 696 trace_qxl_ring_res_push_rest(d->id, ring->prod - ring->cons, 697 ring->num_items, ring->prod, ring->cons); 698 if (notify) { 699 qxl_send_events(d, QXL_INTERRUPT_DISPLAY); 700 } 701 SPICE_RING_PROD_ITEM(d, ring, item); 702 if (!item) { 703 return; 704 } 705 *item = 0; 706 d->num_free_res = 0; 707 d->last_release = NULL; 708 qxl_ring_set_dirty(d); 709 } 710 711 /* called from spice server thread context only */ 712 static void interface_release_resource(QXLInstance *sin, 713 QXLReleaseInfoExt ext) 714 { 715 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 716 QXLReleaseRing *ring; 717 uint64_t *item, id; 718 719 if (ext.group_id == MEMSLOT_GROUP_HOST) { 720 /* host group -> vga mode update request */ 721 QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id); 722 SimpleSpiceUpdate *update; 723 g_assert(cmdext->cmd.type == QXL_CMD_DRAW); 724 update = container_of(cmdext, SimpleSpiceUpdate, ext); 725 qemu_spice_destroy_update(&qxl->ssd, update); 726 return; 727 } 728 729 /* 730 * ext->info points into guest-visible memory 731 * pci bar 0, $command.release_info 732 */ 733 ring = &qxl->ram->release_ring; 734 SPICE_RING_PROD_ITEM(qxl, ring, item); 735 if (!item) { 736 return; 737 } 738 if (*item == 0) { 739 /* stick head into the ring */ 740 id = ext.info->id; 741 ext.info->next = 0; 742 qxl_ram_set_dirty(qxl, &ext.info->next); 743 *item = id; 744 qxl_ring_set_dirty(qxl); 745 } else { 746 /* append item to the list */ 747 qxl->last_release->next = ext.info->id; 748 qxl_ram_set_dirty(qxl, &qxl->last_release->next); 749 ext.info->next = 0; 750 qxl_ram_set_dirty(qxl, &ext.info->next); 751 } 752 qxl->last_release = ext.info; 753 qxl->num_free_res++; 754 trace_qxl_ring_res_put(qxl->id, qxl->num_free_res); 755 qxl_push_free_res(qxl, 0); 756 } 757 758 /* called from spice server thread context only */ 759 static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext) 760 { 761 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 762 QXLCursorRing *ring; 763 QXLCommand *cmd; 764 int notify; 765 766 trace_qxl_ring_cursor_check(qxl->id, qxl_mode_to_string(qxl->mode)); 767 768 switch (qxl->mode) { 769 case QXL_MODE_COMPAT: 770 case QXL_MODE_NATIVE: 771 case QXL_MODE_UNDEFINED: 772 ring = &qxl->ram->cursor_ring; 773 if (SPICE_RING_IS_EMPTY(ring)) { 774 return false; 775 } 776 SPICE_RING_CONS_ITEM(qxl, ring, cmd); 777 if (!cmd) { 778 return false; 779 } 780 ext->cmd = *cmd; 781 ext->group_id = MEMSLOT_GROUP_GUEST; 782 ext->flags = qxl->cmdflags; 783 SPICE_RING_POP(ring, notify); 784 qxl_ring_set_dirty(qxl); 785 if (notify) { 786 qxl_send_events(qxl, QXL_INTERRUPT_CURSOR); 787 } 788 qxl->guest_primary.commands++; 789 qxl_track_command(qxl, ext); 790 qxl_log_command(qxl, "csr", ext); 791 if (qxl->id == 0) { 792 qxl_render_cursor(qxl, ext); 793 } 794 trace_qxl_ring_cursor_get(qxl->id, qxl_mode_to_string(qxl->mode)); 795 return true; 796 default: 797 return false; 798 } 799 } 800 801 /* called from spice server thread context only */ 802 static int interface_req_cursor_notification(QXLInstance *sin) 803 { 804 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 805 int wait = 1; 806 807 trace_qxl_ring_cursor_req_notification(qxl->id); 808 switch (qxl->mode) { 809 case QXL_MODE_COMPAT: 810 case QXL_MODE_NATIVE: 811 case QXL_MODE_UNDEFINED: 812 SPICE_RING_CONS_WAIT(&qxl->ram->cursor_ring, wait); 813 qxl_ring_set_dirty(qxl); 814 break; 815 default: 816 /* nothing */ 817 break; 818 } 819 return wait; 820 } 821 822 /* called from spice server thread context */ 823 static void interface_notify_update(QXLInstance *sin, uint32_t update_id) 824 { 825 /* 826 * Called by spice-server as a result of a QXL_CMD_UPDATE which is not in 827 * use by xf86-video-qxl and is defined out in the qxl windows driver. 828 * Probably was at some earlier version that is prior to git start (2009), 829 * and is still guest trigerrable. 830 */ 831 fprintf(stderr, "%s: deprecated\n", __func__); 832 } 833 834 /* called from spice server thread context only */ 835 static int interface_flush_resources(QXLInstance *sin) 836 { 837 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 838 int ret; 839 840 ret = qxl->num_free_res; 841 if (ret) { 842 qxl_push_free_res(qxl, 1); 843 } 844 return ret; 845 } 846 847 static void qxl_create_guest_primary_complete(PCIQXLDevice *d); 848 849 /* called from spice server thread context only */ 850 static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie) 851 { 852 uint32_t current_async; 853 854 qemu_mutex_lock(&qxl->async_lock); 855 current_async = qxl->current_async; 856 qxl->current_async = QXL_UNDEFINED_IO; 857 qemu_mutex_unlock(&qxl->async_lock); 858 859 trace_qxl_interface_async_complete_io(qxl->id, current_async, cookie); 860 if (!cookie) { 861 fprintf(stderr, "qxl: %s: error, cookie is NULL\n", __func__); 862 return; 863 } 864 if (cookie && current_async != cookie->io) { 865 fprintf(stderr, 866 "qxl: %s: error: current_async = %d != %" 867 PRId64 " = cookie->io\n", __func__, current_async, cookie->io); 868 } 869 switch (current_async) { 870 case QXL_IO_MEMSLOT_ADD_ASYNC: 871 case QXL_IO_DESTROY_PRIMARY_ASYNC: 872 case QXL_IO_UPDATE_AREA_ASYNC: 873 case QXL_IO_FLUSH_SURFACES_ASYNC: 874 case QXL_IO_MONITORS_CONFIG_ASYNC: 875 break; 876 case QXL_IO_CREATE_PRIMARY_ASYNC: 877 qxl_create_guest_primary_complete(qxl); 878 break; 879 case QXL_IO_DESTROY_ALL_SURFACES_ASYNC: 880 qxl_spice_destroy_surfaces_complete(qxl); 881 break; 882 case QXL_IO_DESTROY_SURFACE_ASYNC: 883 qxl_spice_destroy_surface_wait_complete(qxl, cookie->u.surface_id); 884 break; 885 default: 886 fprintf(stderr, "qxl: %s: unexpected current_async %d\n", __func__, 887 current_async); 888 } 889 qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD); 890 } 891 892 /* called from spice server thread context only */ 893 static void interface_update_area_complete(QXLInstance *sin, 894 uint32_t surface_id, 895 QXLRect *dirty, uint32_t num_updated_rects) 896 { 897 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 898 int i; 899 int qxl_i; 900 901 qemu_mutex_lock(&qxl->ssd.lock); 902 if (surface_id != 0 || !num_updated_rects || 903 !qxl->render_update_cookie_num) { 904 qemu_mutex_unlock(&qxl->ssd.lock); 905 return; 906 } 907 trace_qxl_interface_update_area_complete(qxl->id, surface_id, dirty->left, 908 dirty->right, dirty->top, dirty->bottom); 909 trace_qxl_interface_update_area_complete_rest(qxl->id, num_updated_rects); 910 if (qxl->num_dirty_rects + num_updated_rects > QXL_NUM_DIRTY_RECTS) { 911 /* 912 * overflow - treat this as a full update. Not expected to be common. 913 */ 914 trace_qxl_interface_update_area_complete_overflow(qxl->id, 915 QXL_NUM_DIRTY_RECTS); 916 qxl->guest_primary.resized = 1; 917 } 918 if (qxl->guest_primary.resized) { 919 /* 920 * Don't bother copying or scheduling the bh since we will flip 921 * the whole area anyway on completion of the update_area async call 922 */ 923 qemu_mutex_unlock(&qxl->ssd.lock); 924 return; 925 } 926 qxl_i = qxl->num_dirty_rects; 927 for (i = 0; i < num_updated_rects; i++) { 928 qxl->dirty[qxl_i++] = dirty[i]; 929 } 930 qxl->num_dirty_rects += num_updated_rects; 931 trace_qxl_interface_update_area_complete_schedule_bh(qxl->id, 932 qxl->num_dirty_rects); 933 qemu_bh_schedule(qxl->update_area_bh); 934 qemu_mutex_unlock(&qxl->ssd.lock); 935 } 936 937 /* called from spice server thread context only */ 938 static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token) 939 { 940 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 941 QXLCookie *cookie = (QXLCookie *)(uintptr_t)cookie_token; 942 943 switch (cookie->type) { 944 case QXL_COOKIE_TYPE_IO: 945 interface_async_complete_io(qxl, cookie); 946 g_free(cookie); 947 break; 948 case QXL_COOKIE_TYPE_RENDER_UPDATE_AREA: 949 qxl_render_update_area_done(qxl, cookie); 950 break; 951 case QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG: 952 break; 953 default: 954 fprintf(stderr, "qxl: %s: unexpected cookie type %d\n", 955 __func__, cookie->type); 956 g_free(cookie); 957 } 958 } 959 960 /* called from spice server thread context only */ 961 static void interface_set_client_capabilities(QXLInstance *sin, 962 uint8_t client_present, 963 uint8_t caps[58]) 964 { 965 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 966 967 if (qxl->revision < 4) { 968 trace_qxl_set_client_capabilities_unsupported_by_revision(qxl->id, 969 qxl->revision); 970 return; 971 } 972 973 if (runstate_check(RUN_STATE_INMIGRATE) || 974 runstate_check(RUN_STATE_POSTMIGRATE)) { 975 return; 976 } 977 978 qxl->shadow_rom.client_present = client_present; 979 memcpy(qxl->shadow_rom.client_capabilities, caps, 980 sizeof(qxl->shadow_rom.client_capabilities)); 981 qxl->rom->client_present = client_present; 982 memcpy(qxl->rom->client_capabilities, caps, 983 sizeof(qxl->rom->client_capabilities)); 984 qxl_rom_set_dirty(qxl); 985 986 qxl_send_events(qxl, QXL_INTERRUPT_CLIENT); 987 } 988 989 static uint32_t qxl_crc32(const uint8_t *p, unsigned len) 990 { 991 /* 992 * zlib xors the seed with 0xffffffff, and xors the result 993 * again with 0xffffffff; Both are not done with linux's crc32, 994 * which we want to be compatible with, so undo that. 995 */ 996 return crc32(0xffffffff, p, len) ^ 0xffffffff; 997 } 998 999 static bool qxl_rom_monitors_config_changed(QXLRom *rom, 1000 VDAgentMonitorsConfig *monitors_config, 1001 unsigned int max_outputs) 1002 { 1003 int i; 1004 unsigned int monitors_count; 1005 1006 monitors_count = MIN(monitors_config->num_of_monitors, max_outputs); 1007 1008 if (rom->client_monitors_config.count != monitors_count) { 1009 return true; 1010 } 1011 1012 for (i = 0 ; i < rom->client_monitors_config.count ; ++i) { 1013 VDAgentMonConfig *monitor = &monitors_config->monitors[i]; 1014 QXLURect *rect = &rom->client_monitors_config.heads[i]; 1015 /* monitor->depth ignored */ 1016 if ((rect->left != monitor->x) || 1017 (rect->top != monitor->y) || 1018 (rect->right != monitor->x + monitor->width) || 1019 (rect->bottom != monitor->y + monitor->height)) { 1020 return true; 1021 } 1022 } 1023 1024 return false; 1025 } 1026 1027 /* called from main context only */ 1028 static int interface_client_monitors_config(QXLInstance *sin, 1029 VDAgentMonitorsConfig *monitors_config) 1030 { 1031 PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); 1032 QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar); 1033 int i; 1034 unsigned max_outputs = ARRAY_SIZE(rom->client_monitors_config.heads); 1035 bool config_changed = false; 1036 1037 if (qxl->revision < 4) { 1038 trace_qxl_client_monitors_config_unsupported_by_device(qxl->id, 1039 qxl->revision); 1040 return 0; 1041 } 1042 /* 1043 * Older windows drivers set int_mask to 0 when their ISR is called, 1044 * then later set it to ~0. So it doesn't relate to the actual interrupts 1045 * handled. However, they are old, so clearly they don't support this 1046 * interrupt 1047 */ 1048 if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 || 1049 !(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) { 1050 trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id, 1051 qxl->ram->int_mask, 1052 monitors_config); 1053 return 0; 1054 } 1055 if (!monitors_config) { 1056 return 1; 1057 } 1058 1059 #if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */ 1060 /* limit number of outputs based on setting limit */ 1061 if (qxl->max_outputs && qxl->max_outputs <= max_outputs) { 1062 max_outputs = qxl->max_outputs; 1063 } 1064 #endif 1065 1066 config_changed = qxl_rom_monitors_config_changed(rom, 1067 monitors_config, 1068 max_outputs); 1069 1070 memset(&rom->client_monitors_config, 0, 1071 sizeof(rom->client_monitors_config)); 1072 rom->client_monitors_config.count = monitors_config->num_of_monitors; 1073 /* monitors_config->flags ignored */ 1074 if (rom->client_monitors_config.count >= max_outputs) { 1075 trace_qxl_client_monitors_config_capped(qxl->id, 1076 monitors_config->num_of_monitors, 1077 max_outputs); 1078 rom->client_monitors_config.count = max_outputs; 1079 } 1080 for (i = 0 ; i < rom->client_monitors_config.count ; ++i) { 1081 VDAgentMonConfig *monitor = &monitors_config->monitors[i]; 1082 QXLURect *rect = &rom->client_monitors_config.heads[i]; 1083 /* monitor->depth ignored */ 1084 rect->left = monitor->x; 1085 rect->top = monitor->y; 1086 rect->right = monitor->x + monitor->width; 1087 rect->bottom = monitor->y + monitor->height; 1088 } 1089 rom->client_monitors_config_crc = qxl_crc32( 1090 (const uint8_t *)&rom->client_monitors_config, 1091 sizeof(rom->client_monitors_config)); 1092 trace_qxl_client_monitors_config_crc(qxl->id, 1093 sizeof(rom->client_monitors_config), 1094 rom->client_monitors_config_crc); 1095 1096 trace_qxl_interrupt_client_monitors_config(qxl->id, 1097 rom->client_monitors_config.count, 1098 rom->client_monitors_config.heads); 1099 if (config_changed) { 1100 qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG); 1101 } 1102 return 1; 1103 } 1104 1105 static const QXLInterface qxl_interface = { 1106 .base.type = SPICE_INTERFACE_QXL, 1107 .base.description = "qxl gpu", 1108 .base.major_version = SPICE_INTERFACE_QXL_MAJOR, 1109 .base.minor_version = SPICE_INTERFACE_QXL_MINOR, 1110 1111 .attache_worker = interface_attach_worker, 1112 .set_compression_level = interface_set_compression_level, 1113 #if SPICE_NEEDS_SET_MM_TIME 1114 .set_mm_time = interface_set_mm_time, 1115 #endif 1116 .get_init_info = interface_get_init_info, 1117 1118 /* the callbacks below are called from spice server thread context */ 1119 .get_command = interface_get_command, 1120 .req_cmd_notification = interface_req_cmd_notification, 1121 .release_resource = interface_release_resource, 1122 .get_cursor_command = interface_get_cursor_command, 1123 .req_cursor_notification = interface_req_cursor_notification, 1124 .notify_update = interface_notify_update, 1125 .flush_resources = interface_flush_resources, 1126 .async_complete = interface_async_complete, 1127 .update_area_complete = interface_update_area_complete, 1128 .set_client_capabilities = interface_set_client_capabilities, 1129 .client_monitors_config = interface_client_monitors_config, 1130 }; 1131 1132 static const GraphicHwOps qxl_ops = { 1133 .gfx_update = qxl_hw_update, 1134 }; 1135 1136 static void qxl_enter_vga_mode(PCIQXLDevice *d) 1137 { 1138 if (d->mode == QXL_MODE_VGA) { 1139 return; 1140 } 1141 trace_qxl_enter_vga_mode(d->id); 1142 #if SPICE_SERVER_VERSION >= 0x000c03 /* release 0.12.3 */ 1143 spice_qxl_driver_unload(&d->ssd.qxl); 1144 #endif 1145 graphic_console_set_hwops(d->ssd.dcl.con, d->vga.hw_ops, &d->vga); 1146 update_displaychangelistener(&d->ssd.dcl, GUI_REFRESH_INTERVAL_DEFAULT); 1147 qemu_spice_create_host_primary(&d->ssd); 1148 d->mode = QXL_MODE_VGA; 1149 vga_dirty_log_start(&d->vga); 1150 graphic_hw_update(d->vga.con); 1151 } 1152 1153 static void qxl_exit_vga_mode(PCIQXLDevice *d) 1154 { 1155 if (d->mode != QXL_MODE_VGA) { 1156 return; 1157 } 1158 trace_qxl_exit_vga_mode(d->id); 1159 graphic_console_set_hwops(d->ssd.dcl.con, &qxl_ops, d); 1160 update_displaychangelistener(&d->ssd.dcl, GUI_REFRESH_INTERVAL_IDLE); 1161 vga_dirty_log_stop(&d->vga); 1162 qxl_destroy_primary(d, QXL_SYNC); 1163 } 1164 1165 static void qxl_update_irq(PCIQXLDevice *d) 1166 { 1167 uint32_t pending = le32_to_cpu(d->ram->int_pending); 1168 uint32_t mask = le32_to_cpu(d->ram->int_mask); 1169 int level = !!(pending & mask); 1170 pci_set_irq(&d->pci, level); 1171 qxl_ring_set_dirty(d); 1172 } 1173 1174 static void qxl_check_state(PCIQXLDevice *d) 1175 { 1176 QXLRam *ram = d->ram; 1177 int spice_display_running = qemu_spice_display_is_running(&d->ssd); 1178 1179 assert(!spice_display_running || SPICE_RING_IS_EMPTY(&ram->cmd_ring)); 1180 assert(!spice_display_running || SPICE_RING_IS_EMPTY(&ram->cursor_ring)); 1181 } 1182 1183 static void qxl_reset_state(PCIQXLDevice *d) 1184 { 1185 QXLRom *rom = d->rom; 1186 1187 qxl_check_state(d); 1188 d->shadow_rom.update_id = cpu_to_le32(0); 1189 *rom = d->shadow_rom; 1190 qxl_rom_set_dirty(d); 1191 init_qxl_ram(d); 1192 d->num_free_res = 0; 1193 d->last_release = NULL; 1194 memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty)); 1195 qxl_update_irq(d); 1196 } 1197 1198 static void qxl_soft_reset(PCIQXLDevice *d) 1199 { 1200 trace_qxl_soft_reset(d->id); 1201 qxl_check_state(d); 1202 qxl_clear_guest_bug(d); 1203 qemu_mutex_lock(&d->async_lock); 1204 d->current_async = QXL_UNDEFINED_IO; 1205 qemu_mutex_unlock(&d->async_lock); 1206 1207 if (d->id == 0) { 1208 qxl_enter_vga_mode(d); 1209 } else { 1210 d->mode = QXL_MODE_UNDEFINED; 1211 } 1212 } 1213 1214 static void qxl_hard_reset(PCIQXLDevice *d, int loadvm) 1215 { 1216 bool startstop = qemu_spice_display_is_running(&d->ssd); 1217 1218 trace_qxl_hard_reset(d->id, loadvm); 1219 1220 if (startstop) { 1221 qemu_spice_display_stop(); 1222 } 1223 1224 qxl_spice_reset_cursor(d); 1225 qxl_spice_reset_image_cache(d); 1226 qxl_reset_surfaces(d); 1227 qxl_reset_memslots(d); 1228 1229 /* pre loadvm reset must not touch QXLRam. This lives in 1230 * device memory, is migrated together with RAM and thus 1231 * already loaded at this point */ 1232 if (!loadvm) { 1233 qxl_reset_state(d); 1234 } 1235 qemu_spice_create_host_memslot(&d->ssd); 1236 qxl_soft_reset(d); 1237 1238 if (startstop) { 1239 qemu_spice_display_start(); 1240 } 1241 } 1242 1243 static void qxl_reset_handler(DeviceState *dev) 1244 { 1245 PCIQXLDevice *d = PCI_QXL(PCI_DEVICE(dev)); 1246 1247 qxl_hard_reset(d, 0); 1248 } 1249 1250 static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) 1251 { 1252 VGACommonState *vga = opaque; 1253 PCIQXLDevice *qxl = container_of(vga, PCIQXLDevice, vga); 1254 1255 trace_qxl_io_write_vga(qxl->id, qxl_mode_to_string(qxl->mode), addr, val); 1256 if (qxl->mode != QXL_MODE_VGA) { 1257 qxl_destroy_primary(qxl, QXL_SYNC); 1258 qxl_soft_reset(qxl); 1259 } 1260 vga_ioport_write(opaque, addr, val); 1261 } 1262 1263 static const MemoryRegionPortio qxl_vga_portio_list[] = { 1264 { 0x04, 2, 1, .read = vga_ioport_read, 1265 .write = qxl_vga_ioport_write }, /* 3b4 */ 1266 { 0x0a, 1, 1, .read = vga_ioport_read, 1267 .write = qxl_vga_ioport_write }, /* 3ba */ 1268 { 0x10, 16, 1, .read = vga_ioport_read, 1269 .write = qxl_vga_ioport_write }, /* 3c0 */ 1270 { 0x24, 2, 1, .read = vga_ioport_read, 1271 .write = qxl_vga_ioport_write }, /* 3d4 */ 1272 { 0x2a, 1, 1, .read = vga_ioport_read, 1273 .write = qxl_vga_ioport_write }, /* 3da */ 1274 PORTIO_END_OF_LIST(), 1275 }; 1276 1277 static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta, 1278 qxl_async_io async) 1279 { 1280 static const int regions[] = { 1281 QXL_RAM_RANGE_INDEX, 1282 QXL_VRAM_RANGE_INDEX, 1283 QXL_VRAM64_RANGE_INDEX, 1284 }; 1285 uint64_t guest_start; 1286 uint64_t guest_end; 1287 int pci_region; 1288 pcibus_t pci_start; 1289 pcibus_t pci_end; 1290 MemoryRegion *mr; 1291 intptr_t virt_start; 1292 QXLDevMemSlot memslot; 1293 int i; 1294 1295 guest_start = le64_to_cpu(d->guest_slots[slot_id].slot.mem_start); 1296 guest_end = le64_to_cpu(d->guest_slots[slot_id].slot.mem_end); 1297 1298 trace_qxl_memslot_add_guest(d->id, slot_id, guest_start, guest_end); 1299 1300 if (slot_id >= NUM_MEMSLOTS) { 1301 qxl_set_guest_bug(d, "%s: slot_id >= NUM_MEMSLOTS %d >= %d", __func__, 1302 slot_id, NUM_MEMSLOTS); 1303 return 1; 1304 } 1305 if (guest_start > guest_end) { 1306 qxl_set_guest_bug(d, "%s: guest_start > guest_end 0x%" PRIx64 1307 " > 0x%" PRIx64, __func__, guest_start, guest_end); 1308 return 1; 1309 } 1310 1311 for (i = 0; i < ARRAY_SIZE(regions); i++) { 1312 pci_region = regions[i]; 1313 pci_start = d->pci.io_regions[pci_region].addr; 1314 pci_end = pci_start + d->pci.io_regions[pci_region].size; 1315 /* mapped? */ 1316 if (pci_start == -1) { 1317 continue; 1318 } 1319 /* start address in range ? */ 1320 if (guest_start < pci_start || guest_start > pci_end) { 1321 continue; 1322 } 1323 /* end address in range ? */ 1324 if (guest_end > pci_end) { 1325 continue; 1326 } 1327 /* passed */ 1328 break; 1329 } 1330 if (i == ARRAY_SIZE(regions)) { 1331 qxl_set_guest_bug(d, "%s: finished loop without match", __func__); 1332 return 1; 1333 } 1334 1335 switch (pci_region) { 1336 case QXL_RAM_RANGE_INDEX: 1337 mr = &d->vga.vram; 1338 break; 1339 case QXL_VRAM_RANGE_INDEX: 1340 case 4 /* vram 64bit */: 1341 mr = &d->vram_bar; 1342 break; 1343 default: 1344 /* should not happen */ 1345 qxl_set_guest_bug(d, "%s: pci_region = %d", __func__, pci_region); 1346 return 1; 1347 } 1348 1349 virt_start = (intptr_t)memory_region_get_ram_ptr(mr); 1350 memslot.slot_id = slot_id; 1351 memslot.slot_group_id = MEMSLOT_GROUP_GUEST; /* guest group */ 1352 memslot.virt_start = virt_start + (guest_start - pci_start); 1353 memslot.virt_end = virt_start + (guest_end - pci_start); 1354 memslot.addr_delta = memslot.virt_start - delta; 1355 memslot.generation = d->rom->slot_generation = 0; 1356 qxl_rom_set_dirty(d); 1357 1358 qemu_spice_add_memslot(&d->ssd, &memslot, async); 1359 d->guest_slots[slot_id].mr = mr; 1360 d->guest_slots[slot_id].offset = memslot.virt_start - virt_start; 1361 d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start; 1362 d->guest_slots[slot_id].delta = delta; 1363 d->guest_slots[slot_id].active = 1; 1364 return 0; 1365 } 1366 1367 static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id) 1368 { 1369 qemu_spice_del_memslot(&d->ssd, MEMSLOT_GROUP_HOST, slot_id); 1370 d->guest_slots[slot_id].active = 0; 1371 } 1372 1373 static void qxl_reset_memslots(PCIQXLDevice *d) 1374 { 1375 qxl_spice_reset_memslots(d); 1376 memset(&d->guest_slots, 0, sizeof(d->guest_slots)); 1377 } 1378 1379 static void qxl_reset_surfaces(PCIQXLDevice *d) 1380 { 1381 trace_qxl_reset_surfaces(d->id); 1382 d->mode = QXL_MODE_UNDEFINED; 1383 qxl_spice_destroy_surfaces(d, QXL_SYNC); 1384 } 1385 1386 /* can be also called from spice server thread context */ 1387 static bool qxl_get_check_slot_offset(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, 1388 uint32_t *s, uint64_t *o) 1389 { 1390 uint64_t phys = le64_to_cpu(pqxl); 1391 uint32_t slot = (phys >> (64 - 8)) & 0xff; 1392 uint64_t offset = phys & 0xffffffffffff; 1393 1394 if (slot >= NUM_MEMSLOTS) { 1395 qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot, 1396 NUM_MEMSLOTS); 1397 return false; 1398 } 1399 if (!qxl->guest_slots[slot].active) { 1400 qxl_set_guest_bug(qxl, "inactive slot %d\n", slot); 1401 return false; 1402 } 1403 if (offset < qxl->guest_slots[slot].delta) { 1404 qxl_set_guest_bug(qxl, 1405 "slot %d offset %"PRIu64" < delta %"PRIu64"\n", 1406 slot, offset, qxl->guest_slots[slot].delta); 1407 return false; 1408 } 1409 offset -= qxl->guest_slots[slot].delta; 1410 if (offset > qxl->guest_slots[slot].size) { 1411 qxl_set_guest_bug(qxl, 1412 "slot %d offset %"PRIu64" > size %"PRIu64"\n", 1413 slot, offset, qxl->guest_slots[slot].size); 1414 return false; 1415 } 1416 1417 *s = slot; 1418 *o = offset; 1419 return true; 1420 } 1421 1422 /* can be also called from spice server thread context */ 1423 void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id) 1424 { 1425 uint64_t offset; 1426 uint32_t slot; 1427 void *ptr; 1428 1429 switch (group_id) { 1430 case MEMSLOT_GROUP_HOST: 1431 offset = le64_to_cpu(pqxl) & 0xffffffffffff; 1432 return (void *)(intptr_t)offset; 1433 case MEMSLOT_GROUP_GUEST: 1434 if (!qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset)) { 1435 return NULL; 1436 } 1437 ptr = memory_region_get_ram_ptr(qxl->guest_slots[slot].mr); 1438 ptr += qxl->guest_slots[slot].offset; 1439 ptr += offset; 1440 return ptr; 1441 } 1442 return NULL; 1443 } 1444 1445 static void qxl_create_guest_primary_complete(PCIQXLDevice *qxl) 1446 { 1447 /* for local rendering */ 1448 qxl_render_resize(qxl); 1449 } 1450 1451 static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm, 1452 qxl_async_io async) 1453 { 1454 QXLDevSurfaceCreate surface; 1455 QXLSurfaceCreate *sc = &qxl->guest_primary.surface; 1456 uint32_t requested_height = le32_to_cpu(sc->height); 1457 int requested_stride = le32_to_cpu(sc->stride); 1458 1459 if (requested_stride == INT32_MIN || 1460 abs(requested_stride) * (uint64_t)requested_height 1461 > qxl->vgamem_size) { 1462 qxl_set_guest_bug(qxl, "%s: requested primary larger than framebuffer" 1463 " stride %d x height %" PRIu32 " > %" PRIu32, 1464 __func__, requested_stride, requested_height, 1465 qxl->vgamem_size); 1466 return; 1467 } 1468 1469 if (qxl->mode == QXL_MODE_NATIVE) { 1470 qxl_set_guest_bug(qxl, "%s: nop since already in QXL_MODE_NATIVE", 1471 __func__); 1472 } 1473 qxl_exit_vga_mode(qxl); 1474 1475 surface.format = le32_to_cpu(sc->format); 1476 surface.height = le32_to_cpu(sc->height); 1477 surface.mem = le64_to_cpu(sc->mem); 1478 surface.position = le32_to_cpu(sc->position); 1479 surface.stride = le32_to_cpu(sc->stride); 1480 surface.width = le32_to_cpu(sc->width); 1481 surface.type = le32_to_cpu(sc->type); 1482 surface.flags = le32_to_cpu(sc->flags); 1483 trace_qxl_create_guest_primary(qxl->id, sc->width, sc->height, sc->mem, 1484 sc->format, sc->position); 1485 trace_qxl_create_guest_primary_rest(qxl->id, sc->stride, sc->type, 1486 sc->flags); 1487 1488 if ((surface.stride & 0x3) != 0) { 1489 qxl_set_guest_bug(qxl, "primary surface stride = %d %% 4 != 0", 1490 surface.stride); 1491 return; 1492 } 1493 1494 surface.mouse_mode = true; 1495 surface.group_id = MEMSLOT_GROUP_GUEST; 1496 if (loadvm) { 1497 surface.flags |= QXL_SURF_FLAG_KEEP_DATA; 1498 } 1499 1500 qxl->mode = QXL_MODE_NATIVE; 1501 qxl->cmdflags = 0; 1502 qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface, async); 1503 1504 if (async == QXL_SYNC) { 1505 qxl_create_guest_primary_complete(qxl); 1506 } 1507 } 1508 1509 /* return 1 if surface destoy was initiated (in QXL_ASYNC case) or 1510 * done (in QXL_SYNC case), 0 otherwise. */ 1511 static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async) 1512 { 1513 if (d->mode == QXL_MODE_UNDEFINED) { 1514 return 0; 1515 } 1516 trace_qxl_destroy_primary(d->id); 1517 d->mode = QXL_MODE_UNDEFINED; 1518 qemu_spice_destroy_primary_surface(&d->ssd, 0, async); 1519 qxl_spice_reset_cursor(d); 1520 return 1; 1521 } 1522 1523 static void qxl_set_mode(PCIQXLDevice *d, unsigned int modenr, int loadvm) 1524 { 1525 pcibus_t start = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr; 1526 pcibus_t end = d->pci.io_regions[QXL_RAM_RANGE_INDEX].size + start; 1527 QXLMode *mode = d->modes->modes + modenr; 1528 uint64_t devmem = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr; 1529 QXLMemSlot slot = { 1530 .mem_start = start, 1531 .mem_end = end 1532 }; 1533 1534 if (modenr >= d->modes->n_modes) { 1535 qxl_set_guest_bug(d, "mode number out of range"); 1536 return; 1537 } 1538 1539 QXLSurfaceCreate surface = { 1540 .width = mode->x_res, 1541 .height = mode->y_res, 1542 .stride = -mode->x_res * 4, 1543 .format = SPICE_SURFACE_FMT_32_xRGB, 1544 .flags = loadvm ? QXL_SURF_FLAG_KEEP_DATA : 0, 1545 .mouse_mode = true, 1546 .mem = devmem + d->shadow_rom.draw_area_offset, 1547 }; 1548 1549 trace_qxl_set_mode(d->id, modenr, mode->x_res, mode->y_res, mode->bits, 1550 devmem); 1551 if (!loadvm) { 1552 qxl_hard_reset(d, 0); 1553 } 1554 1555 d->guest_slots[0].slot = slot; 1556 assert(qxl_add_memslot(d, 0, devmem, QXL_SYNC) == 0); 1557 1558 d->guest_primary.surface = surface; 1559 qxl_create_guest_primary(d, 0, QXL_SYNC); 1560 1561 d->mode = QXL_MODE_COMPAT; 1562 d->cmdflags = QXL_COMMAND_FLAG_COMPAT; 1563 if (mode->bits == 16) { 1564 d->cmdflags |= QXL_COMMAND_FLAG_COMPAT_16BPP; 1565 } 1566 d->shadow_rom.mode = cpu_to_le32(modenr); 1567 d->rom->mode = cpu_to_le32(modenr); 1568 qxl_rom_set_dirty(d); 1569 } 1570 1571 static void ioport_write(void *opaque, hwaddr addr, 1572 uint64_t val, unsigned size) 1573 { 1574 PCIQXLDevice *d = opaque; 1575 uint32_t io_port = addr; 1576 qxl_async_io async = QXL_SYNC; 1577 uint32_t orig_io_port = io_port; 1578 1579 if (d->guest_bug && io_port != QXL_IO_RESET) { 1580 return; 1581 } 1582 1583 if (d->revision <= QXL_REVISION_STABLE_V10 && 1584 io_port > QXL_IO_FLUSH_RELEASE) { 1585 qxl_set_guest_bug(d, "unsupported io %d for revision %d\n", 1586 io_port, d->revision); 1587 return; 1588 } 1589 1590 switch (io_port) { 1591 case QXL_IO_RESET: 1592 case QXL_IO_SET_MODE: 1593 case QXL_IO_MEMSLOT_ADD: 1594 case QXL_IO_MEMSLOT_DEL: 1595 case QXL_IO_CREATE_PRIMARY: 1596 case QXL_IO_UPDATE_IRQ: 1597 case QXL_IO_LOG: 1598 case QXL_IO_MEMSLOT_ADD_ASYNC: 1599 case QXL_IO_CREATE_PRIMARY_ASYNC: 1600 break; 1601 default: 1602 if (d->mode != QXL_MODE_VGA) { 1603 break; 1604 } 1605 trace_qxl_io_unexpected_vga_mode(d->id, 1606 addr, val, io_port_to_string(io_port)); 1607 /* be nice to buggy guest drivers */ 1608 if (io_port >= QXL_IO_UPDATE_AREA_ASYNC && 1609 io_port < QXL_IO_RANGE_SIZE) { 1610 qxl_send_events(d, QXL_INTERRUPT_IO_CMD); 1611 } 1612 return; 1613 } 1614 1615 /* we change the io_port to avoid ifdeffery in the main switch */ 1616 orig_io_port = io_port; 1617 switch (io_port) { 1618 case QXL_IO_UPDATE_AREA_ASYNC: 1619 io_port = QXL_IO_UPDATE_AREA; 1620 goto async_common; 1621 case QXL_IO_MEMSLOT_ADD_ASYNC: 1622 io_port = QXL_IO_MEMSLOT_ADD; 1623 goto async_common; 1624 case QXL_IO_CREATE_PRIMARY_ASYNC: 1625 io_port = QXL_IO_CREATE_PRIMARY; 1626 goto async_common; 1627 case QXL_IO_DESTROY_PRIMARY_ASYNC: 1628 io_port = QXL_IO_DESTROY_PRIMARY; 1629 goto async_common; 1630 case QXL_IO_DESTROY_SURFACE_ASYNC: 1631 io_port = QXL_IO_DESTROY_SURFACE_WAIT; 1632 goto async_common; 1633 case QXL_IO_DESTROY_ALL_SURFACES_ASYNC: 1634 io_port = QXL_IO_DESTROY_ALL_SURFACES; 1635 goto async_common; 1636 case QXL_IO_FLUSH_SURFACES_ASYNC: 1637 case QXL_IO_MONITORS_CONFIG_ASYNC: 1638 async_common: 1639 async = QXL_ASYNC; 1640 qemu_mutex_lock(&d->async_lock); 1641 if (d->current_async != QXL_UNDEFINED_IO) { 1642 qxl_set_guest_bug(d, "%d async started before last (%d) complete", 1643 io_port, d->current_async); 1644 qemu_mutex_unlock(&d->async_lock); 1645 return; 1646 } 1647 d->current_async = orig_io_port; 1648 qemu_mutex_unlock(&d->async_lock); 1649 break; 1650 default: 1651 break; 1652 } 1653 trace_qxl_io_write(d->id, qxl_mode_to_string(d->mode), 1654 addr, io_port_to_string(addr), 1655 val, size, async); 1656 1657 switch (io_port) { 1658 case QXL_IO_UPDATE_AREA: 1659 { 1660 QXLCookie *cookie = NULL; 1661 QXLRect update = d->ram->update_area; 1662 1663 if (d->ram->update_surface > d->ssd.num_surfaces) { 1664 qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: invalid surface id %d\n", 1665 d->ram->update_surface); 1666 break; 1667 } 1668 if (update.left >= update.right || update.top >= update.bottom || 1669 update.left < 0 || update.top < 0) { 1670 qxl_set_guest_bug(d, 1671 "QXL_IO_UPDATE_AREA: invalid area (%ux%u)x(%ux%u)\n", 1672 update.left, update.top, update.right, update.bottom); 1673 if (update.left == update.right || update.top == update.bottom) { 1674 /* old drivers may provide empty area, keep going */ 1675 qxl_clear_guest_bug(d); 1676 goto cancel_async; 1677 } 1678 break; 1679 } 1680 if (async == QXL_ASYNC) { 1681 cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO, 1682 QXL_IO_UPDATE_AREA_ASYNC); 1683 cookie->u.area = update; 1684 } 1685 qxl_spice_update_area(d, d->ram->update_surface, 1686 cookie ? &cookie->u.area : &update, 1687 NULL, 0, 0, async, cookie); 1688 break; 1689 } 1690 case QXL_IO_NOTIFY_CMD: 1691 qemu_spice_wakeup(&d->ssd); 1692 break; 1693 case QXL_IO_NOTIFY_CURSOR: 1694 qemu_spice_wakeup(&d->ssd); 1695 break; 1696 case QXL_IO_UPDATE_IRQ: 1697 qxl_update_irq(d); 1698 break; 1699 case QXL_IO_NOTIFY_OOM: 1700 if (!SPICE_RING_IS_EMPTY(&d->ram->release_ring)) { 1701 break; 1702 } 1703 d->oom_running = 1; 1704 qxl_spice_oom(d); 1705 d->oom_running = 0; 1706 break; 1707 case QXL_IO_SET_MODE: 1708 qxl_set_mode(d, val, 0); 1709 break; 1710 case QXL_IO_LOG: 1711 trace_qxl_io_log(d->id, d->ram->log_buf); 1712 if (d->guestdebug) { 1713 fprintf(stderr, "qxl/guest-%d: %" PRId64 ": %s", d->id, 1714 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), d->ram->log_buf); 1715 } 1716 break; 1717 case QXL_IO_RESET: 1718 qxl_hard_reset(d, 0); 1719 break; 1720 case QXL_IO_MEMSLOT_ADD: 1721 if (val >= NUM_MEMSLOTS) { 1722 qxl_set_guest_bug(d, "QXL_IO_MEMSLOT_ADD: val out of range"); 1723 break; 1724 } 1725 if (d->guest_slots[val].active) { 1726 qxl_set_guest_bug(d, 1727 "QXL_IO_MEMSLOT_ADD: memory slot already active"); 1728 break; 1729 } 1730 d->guest_slots[val].slot = d->ram->mem_slot; 1731 qxl_add_memslot(d, val, 0, async); 1732 break; 1733 case QXL_IO_MEMSLOT_DEL: 1734 if (val >= NUM_MEMSLOTS) { 1735 qxl_set_guest_bug(d, "QXL_IO_MEMSLOT_DEL: val out of range"); 1736 break; 1737 } 1738 qxl_del_memslot(d, val); 1739 break; 1740 case QXL_IO_CREATE_PRIMARY: 1741 if (val != 0) { 1742 qxl_set_guest_bug(d, "QXL_IO_CREATE_PRIMARY (async=%d): val != 0", 1743 async); 1744 goto cancel_async; 1745 } 1746 d->guest_primary.surface = d->ram->create_surface; 1747 qxl_create_guest_primary(d, 0, async); 1748 break; 1749 case QXL_IO_DESTROY_PRIMARY: 1750 if (val != 0) { 1751 qxl_set_guest_bug(d, "QXL_IO_DESTROY_PRIMARY (async=%d): val != 0", 1752 async); 1753 goto cancel_async; 1754 } 1755 if (!qxl_destroy_primary(d, async)) { 1756 trace_qxl_io_destroy_primary_ignored(d->id, 1757 qxl_mode_to_string(d->mode)); 1758 goto cancel_async; 1759 } 1760 break; 1761 case QXL_IO_DESTROY_SURFACE_WAIT: 1762 if (val >= d->ssd.num_surfaces) { 1763 qxl_set_guest_bug(d, "QXL_IO_DESTROY_SURFACE (async=%d):" 1764 "%" PRIu64 " >= NUM_SURFACES", async, val); 1765 goto cancel_async; 1766 } 1767 qxl_spice_destroy_surface_wait(d, val, async); 1768 break; 1769 case QXL_IO_FLUSH_RELEASE: { 1770 QXLReleaseRing *ring = &d->ram->release_ring; 1771 if (ring->prod - ring->cons + 1 == ring->num_items) { 1772 fprintf(stderr, 1773 "ERROR: no flush, full release ring [p%d,%dc]\n", 1774 ring->prod, ring->cons); 1775 } 1776 qxl_push_free_res(d, 1 /* flush */); 1777 break; 1778 } 1779 case QXL_IO_FLUSH_SURFACES_ASYNC: 1780 qxl_spice_flush_surfaces_async(d); 1781 break; 1782 case QXL_IO_DESTROY_ALL_SURFACES: 1783 d->mode = QXL_MODE_UNDEFINED; 1784 qxl_spice_destroy_surfaces(d, async); 1785 break; 1786 case QXL_IO_MONITORS_CONFIG_ASYNC: 1787 qxl_spice_monitors_config_async(d, 0); 1788 break; 1789 default: 1790 qxl_set_guest_bug(d, "%s: unexpected ioport=0x%x\n", __func__, io_port); 1791 } 1792 return; 1793 cancel_async: 1794 if (async) { 1795 qxl_send_events(d, QXL_INTERRUPT_IO_CMD); 1796 qemu_mutex_lock(&d->async_lock); 1797 d->current_async = QXL_UNDEFINED_IO; 1798 qemu_mutex_unlock(&d->async_lock); 1799 } 1800 } 1801 1802 static uint64_t ioport_read(void *opaque, hwaddr addr, 1803 unsigned size) 1804 { 1805 PCIQXLDevice *qxl = opaque; 1806 1807 trace_qxl_io_read_unexpected(qxl->id); 1808 return 0xff; 1809 } 1810 1811 static const MemoryRegionOps qxl_io_ops = { 1812 .read = ioport_read, 1813 .write = ioport_write, 1814 .valid = { 1815 .min_access_size = 1, 1816 .max_access_size = 1, 1817 }, 1818 }; 1819 1820 static void qxl_update_irq_bh(void *opaque) 1821 { 1822 PCIQXLDevice *d = opaque; 1823 qxl_update_irq(d); 1824 } 1825 1826 static void qxl_send_events(PCIQXLDevice *d, uint32_t events) 1827 { 1828 uint32_t old_pending; 1829 uint32_t le_events = cpu_to_le32(events); 1830 1831 trace_qxl_send_events(d->id, events); 1832 if (!qemu_spice_display_is_running(&d->ssd)) { 1833 /* spice-server tracks guest running state and should not do this */ 1834 fprintf(stderr, "%s: spice-server bug: guest stopped, ignoring\n", 1835 __func__); 1836 trace_qxl_send_events_vm_stopped(d->id, events); 1837 return; 1838 } 1839 old_pending = atomic_fetch_or(&d->ram->int_pending, le_events); 1840 if ((old_pending & le_events) == le_events) { 1841 return; 1842 } 1843 qemu_bh_schedule(d->update_irq); 1844 } 1845 1846 /* graphics console */ 1847 1848 static void qxl_hw_update(void *opaque) 1849 { 1850 PCIQXLDevice *qxl = opaque; 1851 1852 qxl_render_update(qxl); 1853 } 1854 1855 static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, 1856 uint32_t height, int32_t stride) 1857 { 1858 uint64_t offset, size; 1859 uint32_t slot; 1860 bool rc; 1861 1862 rc = qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset); 1863 assert(rc == true); 1864 size = (uint64_t)height * abs(stride); 1865 trace_qxl_surfaces_dirty(qxl->id, offset, size); 1866 qxl_set_dirty(qxl->guest_slots[slot].mr, 1867 qxl->guest_slots[slot].offset + offset, 1868 qxl->guest_slots[slot].offset + offset + size); 1869 } 1870 1871 static void qxl_dirty_surfaces(PCIQXLDevice *qxl) 1872 { 1873 int i; 1874 1875 if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) { 1876 return; 1877 } 1878 1879 /* dirty the primary surface */ 1880 qxl_dirty_one_surface(qxl, qxl->guest_primary.surface.mem, 1881 qxl->guest_primary.surface.height, 1882 qxl->guest_primary.surface.stride); 1883 1884 /* dirty the off-screen surfaces */ 1885 for (i = 0; i < qxl->ssd.num_surfaces; i++) { 1886 QXLSurfaceCmd *cmd; 1887 1888 if (qxl->guest_surfaces.cmds[i] == 0) { 1889 continue; 1890 } 1891 1892 cmd = qxl_phys2virt(qxl, qxl->guest_surfaces.cmds[i], 1893 MEMSLOT_GROUP_GUEST); 1894 assert(cmd); 1895 assert(cmd->type == QXL_SURFACE_CMD_CREATE); 1896 qxl_dirty_one_surface(qxl, cmd->u.surface_create.data, 1897 cmd->u.surface_create.height, 1898 cmd->u.surface_create.stride); 1899 } 1900 } 1901 1902 static void qxl_vm_change_state_handler(void *opaque, int running, 1903 RunState state) 1904 { 1905 PCIQXLDevice *qxl = opaque; 1906 1907 if (running) { 1908 /* 1909 * if qxl_send_events was called from spice server context before 1910 * migration ended, qxl_update_irq for these events might not have been 1911 * called 1912 */ 1913 qxl_update_irq(qxl); 1914 } else { 1915 /* make sure surfaces are saved before migration */ 1916 qxl_dirty_surfaces(qxl); 1917 } 1918 } 1919 1920 /* display change listener */ 1921 1922 static void display_update(DisplayChangeListener *dcl, 1923 int x, int y, int w, int h) 1924 { 1925 PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); 1926 1927 if (qxl->mode == QXL_MODE_VGA) { 1928 qemu_spice_display_update(&qxl->ssd, x, y, w, h); 1929 } 1930 } 1931 1932 static void display_switch(DisplayChangeListener *dcl, 1933 struct DisplaySurface *surface) 1934 { 1935 PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); 1936 1937 qxl->ssd.ds = surface; 1938 if (qxl->mode == QXL_MODE_VGA) { 1939 qemu_spice_display_switch(&qxl->ssd, surface); 1940 } 1941 } 1942 1943 static void display_refresh(DisplayChangeListener *dcl) 1944 { 1945 PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); 1946 1947 if (qxl->mode == QXL_MODE_VGA) { 1948 qemu_spice_display_refresh(&qxl->ssd); 1949 } 1950 } 1951 1952 static DisplayChangeListenerOps display_listener_ops = { 1953 .dpy_name = "spice/qxl", 1954 .dpy_gfx_update = display_update, 1955 .dpy_gfx_switch = display_switch, 1956 .dpy_refresh = display_refresh, 1957 }; 1958 1959 static void qxl_init_ramsize(PCIQXLDevice *qxl) 1960 { 1961 /* vga mode framebuffer / primary surface (bar 0, first part) */ 1962 if (qxl->vgamem_size_mb < 8) { 1963 qxl->vgamem_size_mb = 8; 1964 } 1965 /* XXX: we round vgamem_size_mb up to a nearest power of two and it must be 1966 * less than vga_common_init()'s maximum on qxl->vga.vram_size (512 now). 1967 */ 1968 if (qxl->vgamem_size_mb > 256) { 1969 qxl->vgamem_size_mb = 256; 1970 } 1971 qxl->vgamem_size = qxl->vgamem_size_mb * 1024 * 1024; 1972 1973 /* vga ram (bar 0, total) */ 1974 if (qxl->ram_size_mb != -1) { 1975 qxl->vga.vram_size = qxl->ram_size_mb * 1024 * 1024; 1976 } 1977 if (qxl->vga.vram_size < qxl->vgamem_size * 2) { 1978 qxl->vga.vram_size = qxl->vgamem_size * 2; 1979 } 1980 1981 /* vram32 (surfaces, 32bit, bar 1) */ 1982 if (qxl->vram32_size_mb != -1) { 1983 qxl->vram32_size = qxl->vram32_size_mb * 1024 * 1024; 1984 } 1985 if (qxl->vram32_size < 4096) { 1986 qxl->vram32_size = 4096; 1987 } 1988 1989 /* vram (surfaces, 64bit, bar 4+5) */ 1990 if (qxl->vram_size_mb != -1) { 1991 qxl->vram_size = (uint64_t)qxl->vram_size_mb * 1024 * 1024; 1992 } 1993 if (qxl->vram_size < qxl->vram32_size) { 1994 qxl->vram_size = qxl->vram32_size; 1995 } 1996 1997 if (qxl->revision == 1) { 1998 qxl->vram32_size = 4096; 1999 qxl->vram_size = 4096; 2000 } 2001 qxl->vgamem_size = pow2ceil(qxl->vgamem_size); 2002 qxl->vga.vram_size = pow2ceil(qxl->vga.vram_size); 2003 qxl->vram32_size = pow2ceil(qxl->vram32_size); 2004 qxl->vram_size = pow2ceil(qxl->vram_size); 2005 } 2006 2007 static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp) 2008 { 2009 uint8_t* config = qxl->pci.config; 2010 uint32_t pci_device_rev; 2011 uint32_t io_size; 2012 2013 qxl->mode = QXL_MODE_UNDEFINED; 2014 qxl->generation = 1; 2015 qxl->num_memslots = NUM_MEMSLOTS; 2016 qemu_mutex_init(&qxl->track_lock); 2017 qemu_mutex_init(&qxl->async_lock); 2018 qxl->current_async = QXL_UNDEFINED_IO; 2019 qxl->guest_bug = 0; 2020 2021 switch (qxl->revision) { 2022 case 1: /* spice 0.4 -- qxl-1 */ 2023 pci_device_rev = QXL_REVISION_STABLE_V04; 2024 io_size = 8; 2025 break; 2026 case 2: /* spice 0.6 -- qxl-2 */ 2027 pci_device_rev = QXL_REVISION_STABLE_V06; 2028 io_size = 16; 2029 break; 2030 case 3: /* qxl-3 */ 2031 pci_device_rev = QXL_REVISION_STABLE_V10; 2032 io_size = 32; /* PCI region size must be pow2 */ 2033 break; 2034 case 4: /* qxl-4 */ 2035 pci_device_rev = QXL_REVISION_STABLE_V12; 2036 io_size = pow2ceil(QXL_IO_RANGE_SIZE); 2037 break; 2038 default: 2039 error_setg(errp, "Invalid revision %d for qxl device (max %d)", 2040 qxl->revision, QXL_DEFAULT_REVISION); 2041 return; 2042 } 2043 2044 pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev); 2045 pci_set_byte(&config[PCI_INTERRUPT_PIN], 1); 2046 2047 qxl->rom_size = qxl_rom_size(); 2048 memory_region_init_ram(&qxl->rom_bar, OBJECT(qxl), "qxl.vrom", 2049 qxl->rom_size, &error_fatal); 2050 vmstate_register_ram(&qxl->rom_bar, &qxl->pci.qdev); 2051 init_qxl_rom(qxl); 2052 init_qxl_ram(qxl); 2053 2054 qxl->guest_surfaces.cmds = g_new0(QXLPHYSICAL, qxl->ssd.num_surfaces); 2055 memory_region_init_ram(&qxl->vram_bar, OBJECT(qxl), "qxl.vram", 2056 qxl->vram_size, &error_fatal); 2057 vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev); 2058 memory_region_init_alias(&qxl->vram32_bar, OBJECT(qxl), "qxl.vram32", 2059 &qxl->vram_bar, 0, qxl->vram32_size); 2060 2061 memory_region_init_io(&qxl->io_bar, OBJECT(qxl), &qxl_io_ops, qxl, 2062 "qxl-ioports", io_size); 2063 if (qxl->id == 0) { 2064 vga_dirty_log_start(&qxl->vga); 2065 } 2066 memory_region_set_flush_coalesced(&qxl->io_bar); 2067 2068 2069 pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX, 2070 PCI_BASE_ADDRESS_SPACE_IO, &qxl->io_bar); 2071 2072 pci_register_bar(&qxl->pci, QXL_ROM_RANGE_INDEX, 2073 PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->rom_bar); 2074 2075 pci_register_bar(&qxl->pci, QXL_RAM_RANGE_INDEX, 2076 PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vga.vram); 2077 2078 pci_register_bar(&qxl->pci, QXL_VRAM_RANGE_INDEX, 2079 PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vram32_bar); 2080 2081 if (qxl->vram32_size < qxl->vram_size) { 2082 /* 2083 * Make the 64bit vram bar show up only in case it is 2084 * configured to be larger than the 32bit vram bar. 2085 */ 2086 pci_register_bar(&qxl->pci, QXL_VRAM64_RANGE_INDEX, 2087 PCI_BASE_ADDRESS_SPACE_MEMORY | 2088 PCI_BASE_ADDRESS_MEM_TYPE_64 | 2089 PCI_BASE_ADDRESS_MEM_PREFETCH, 2090 &qxl->vram_bar); 2091 } 2092 2093 /* print pci bar details */ 2094 dprint(qxl, 1, "ram/%s: %d MB [region 0]\n", 2095 qxl->id == 0 ? "pri" : "sec", 2096 qxl->vga.vram_size / (1024*1024)); 2097 dprint(qxl, 1, "vram/32: %" PRIx64 "d MB [region 1]\n", 2098 qxl->vram32_size / (1024*1024)); 2099 dprint(qxl, 1, "vram/64: %" PRIx64 "d MB %s\n", 2100 qxl->vram_size / (1024*1024), 2101 qxl->vram32_size < qxl->vram_size ? "[region 4]" : "[unmapped]"); 2102 2103 qxl->ssd.qxl.base.sif = &qxl_interface.base; 2104 if (qemu_spice_add_display_interface(&qxl->ssd.qxl, qxl->vga.con) != 0) { 2105 error_setg(errp, "qxl interface %d.%d not supported by spice-server", 2106 SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR); 2107 return; 2108 } 2109 qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl); 2110 2111 qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl); 2112 qxl_reset_state(qxl); 2113 2114 qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl); 2115 qxl->ssd.cursor_bh = qemu_bh_new(qemu_spice_cursor_refresh_bh, &qxl->ssd); 2116 } 2117 2118 static void qxl_realize_primary(PCIDevice *dev, Error **errp) 2119 { 2120 PCIQXLDevice *qxl = PCI_QXL(dev); 2121 VGACommonState *vga = &qxl->vga; 2122 Error *local_err = NULL; 2123 2124 qxl->id = 0; 2125 qxl_init_ramsize(qxl); 2126 vga->vbe_size = qxl->vgamem_size; 2127 vga->vram_size_mb = qxl->vga.vram_size >> 20; 2128 vga_common_init(vga, OBJECT(dev), true); 2129 vga_init(vga, OBJECT(dev), 2130 pci_address_space(dev), pci_address_space_io(dev), false); 2131 portio_list_init(&qxl->vga_port_list, OBJECT(dev), qxl_vga_portio_list, 2132 vga, "vga"); 2133 portio_list_set_flush_coalesced(&qxl->vga_port_list); 2134 portio_list_add(&qxl->vga_port_list, pci_address_space_io(dev), 0x3b0); 2135 2136 vga->con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl); 2137 qemu_spice_display_init_common(&qxl->ssd); 2138 2139 qxl_realize_common(qxl, &local_err); 2140 if (local_err) { 2141 error_propagate(errp, local_err); 2142 return; 2143 } 2144 2145 qxl->ssd.dcl.ops = &display_listener_ops; 2146 qxl->ssd.dcl.con = vga->con; 2147 register_displaychangelistener(&qxl->ssd.dcl); 2148 } 2149 2150 static void qxl_realize_secondary(PCIDevice *dev, Error **errp) 2151 { 2152 static int device_id = 1; 2153 PCIQXLDevice *qxl = PCI_QXL(dev); 2154 2155 qxl->id = device_id++; 2156 qxl_init_ramsize(qxl); 2157 memory_region_init_ram(&qxl->vga.vram, OBJECT(dev), "qxl.vgavram", 2158 qxl->vga.vram_size, &error_fatal); 2159 vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev); 2160 qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram); 2161 qxl->vga.con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl); 2162 2163 qxl_realize_common(qxl, errp); 2164 } 2165 2166 static void qxl_pre_save(void *opaque) 2167 { 2168 PCIQXLDevice* d = opaque; 2169 uint8_t *ram_start = d->vga.vram_ptr; 2170 2171 trace_qxl_pre_save(d->id); 2172 if (d->last_release == NULL) { 2173 d->last_release_offset = 0; 2174 } else { 2175 d->last_release_offset = (uint8_t *)d->last_release - ram_start; 2176 } 2177 assert(d->last_release_offset < d->vga.vram_size); 2178 } 2179 2180 static int qxl_pre_load(void *opaque) 2181 { 2182 PCIQXLDevice* d = opaque; 2183 2184 trace_qxl_pre_load(d->id); 2185 qxl_hard_reset(d, 1); 2186 qxl_exit_vga_mode(d); 2187 return 0; 2188 } 2189 2190 static void qxl_create_memslots(PCIQXLDevice *d) 2191 { 2192 int i; 2193 2194 for (i = 0; i < NUM_MEMSLOTS; i++) { 2195 if (!d->guest_slots[i].active) { 2196 continue; 2197 } 2198 qxl_add_memslot(d, i, 0, QXL_SYNC); 2199 } 2200 } 2201 2202 static int qxl_post_load(void *opaque, int version) 2203 { 2204 PCIQXLDevice* d = opaque; 2205 uint8_t *ram_start = d->vga.vram_ptr; 2206 QXLCommandExt *cmds; 2207 int in, out, newmode; 2208 2209 assert(d->last_release_offset < d->vga.vram_size); 2210 if (d->last_release_offset == 0) { 2211 d->last_release = NULL; 2212 } else { 2213 d->last_release = (QXLReleaseInfo *)(ram_start + d->last_release_offset); 2214 } 2215 2216 d->modes = (QXLModes*)((uint8_t*)d->rom + d->rom->modes_offset); 2217 2218 trace_qxl_post_load(d->id, qxl_mode_to_string(d->mode)); 2219 newmode = d->mode; 2220 d->mode = QXL_MODE_UNDEFINED; 2221 2222 switch (newmode) { 2223 case QXL_MODE_UNDEFINED: 2224 qxl_create_memslots(d); 2225 break; 2226 case QXL_MODE_VGA: 2227 qxl_create_memslots(d); 2228 qxl_enter_vga_mode(d); 2229 break; 2230 case QXL_MODE_NATIVE: 2231 qxl_create_memslots(d); 2232 qxl_create_guest_primary(d, 1, QXL_SYNC); 2233 2234 /* replay surface-create and cursor-set commands */ 2235 cmds = g_new0(QXLCommandExt, d->ssd.num_surfaces + 1); 2236 for (in = 0, out = 0; in < d->ssd.num_surfaces; in++) { 2237 if (d->guest_surfaces.cmds[in] == 0) { 2238 continue; 2239 } 2240 cmds[out].cmd.data = d->guest_surfaces.cmds[in]; 2241 cmds[out].cmd.type = QXL_CMD_SURFACE; 2242 cmds[out].group_id = MEMSLOT_GROUP_GUEST; 2243 out++; 2244 } 2245 if (d->guest_cursor) { 2246 cmds[out].cmd.data = d->guest_cursor; 2247 cmds[out].cmd.type = QXL_CMD_CURSOR; 2248 cmds[out].group_id = MEMSLOT_GROUP_GUEST; 2249 out++; 2250 } 2251 qxl_spice_loadvm_commands(d, cmds, out); 2252 g_free(cmds); 2253 if (d->guest_monitors_config) { 2254 qxl_spice_monitors_config_async(d, 1); 2255 } 2256 break; 2257 case QXL_MODE_COMPAT: 2258 /* note: no need to call qxl_create_memslots, qxl_set_mode 2259 * creates the mem slot. */ 2260 qxl_set_mode(d, d->shadow_rom.mode, 1); 2261 break; 2262 } 2263 return 0; 2264 } 2265 2266 #define QXL_SAVE_VERSION 21 2267 2268 static bool qxl_monitors_config_needed(void *opaque) 2269 { 2270 PCIQXLDevice *qxl = opaque; 2271 2272 return qxl->guest_monitors_config != 0; 2273 } 2274 2275 2276 static VMStateDescription qxl_memslot = { 2277 .name = "qxl-memslot", 2278 .version_id = QXL_SAVE_VERSION, 2279 .minimum_version_id = QXL_SAVE_VERSION, 2280 .fields = (VMStateField[]) { 2281 VMSTATE_UINT64(slot.mem_start, struct guest_slots), 2282 VMSTATE_UINT64(slot.mem_end, struct guest_slots), 2283 VMSTATE_UINT32(active, struct guest_slots), 2284 VMSTATE_END_OF_LIST() 2285 } 2286 }; 2287 2288 static VMStateDescription qxl_surface = { 2289 .name = "qxl-surface", 2290 .version_id = QXL_SAVE_VERSION, 2291 .minimum_version_id = QXL_SAVE_VERSION, 2292 .fields = (VMStateField[]) { 2293 VMSTATE_UINT32(width, QXLSurfaceCreate), 2294 VMSTATE_UINT32(height, QXLSurfaceCreate), 2295 VMSTATE_INT32(stride, QXLSurfaceCreate), 2296 VMSTATE_UINT32(format, QXLSurfaceCreate), 2297 VMSTATE_UINT32(position, QXLSurfaceCreate), 2298 VMSTATE_UINT32(mouse_mode, QXLSurfaceCreate), 2299 VMSTATE_UINT32(flags, QXLSurfaceCreate), 2300 VMSTATE_UINT32(type, QXLSurfaceCreate), 2301 VMSTATE_UINT64(mem, QXLSurfaceCreate), 2302 VMSTATE_END_OF_LIST() 2303 } 2304 }; 2305 2306 static VMStateDescription qxl_vmstate_monitors_config = { 2307 .name = "qxl/monitors-config", 2308 .version_id = 1, 2309 .minimum_version_id = 1, 2310 .needed = qxl_monitors_config_needed, 2311 .fields = (VMStateField[]) { 2312 VMSTATE_UINT64(guest_monitors_config, PCIQXLDevice), 2313 VMSTATE_END_OF_LIST() 2314 }, 2315 }; 2316 2317 static VMStateDescription qxl_vmstate = { 2318 .name = "qxl", 2319 .version_id = QXL_SAVE_VERSION, 2320 .minimum_version_id = QXL_SAVE_VERSION, 2321 .pre_save = qxl_pre_save, 2322 .pre_load = qxl_pre_load, 2323 .post_load = qxl_post_load, 2324 .fields = (VMStateField[]) { 2325 VMSTATE_PCI_DEVICE(pci, PCIQXLDevice), 2326 VMSTATE_STRUCT(vga, PCIQXLDevice, 0, vmstate_vga_common, VGACommonState), 2327 VMSTATE_UINT32(shadow_rom.mode, PCIQXLDevice), 2328 VMSTATE_UINT32(num_free_res, PCIQXLDevice), 2329 VMSTATE_UINT32(last_release_offset, PCIQXLDevice), 2330 VMSTATE_UINT32(mode, PCIQXLDevice), 2331 VMSTATE_UINT32(ssd.unique, PCIQXLDevice), 2332 VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice), 2333 VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0, 2334 qxl_memslot, struct guest_slots), 2335 VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0, 2336 qxl_surface, QXLSurfaceCreate), 2337 VMSTATE_INT32_EQUAL(ssd.num_surfaces, PCIQXLDevice), 2338 VMSTATE_VARRAY_INT32(guest_surfaces.cmds, PCIQXLDevice, 2339 ssd.num_surfaces, 0, 2340 vmstate_info_uint64, uint64_t), 2341 VMSTATE_UINT64(guest_cursor, PCIQXLDevice), 2342 VMSTATE_END_OF_LIST() 2343 }, 2344 .subsections = (const VMStateDescription*[]) { 2345 &qxl_vmstate_monitors_config, 2346 NULL 2347 } 2348 }; 2349 2350 static Property qxl_properties[] = { 2351 DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 2352 64 * 1024 * 1024), 2353 DEFINE_PROP_UINT64("vram_size", PCIQXLDevice, vram32_size, 2354 64 * 1024 * 1024), 2355 DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2356 QXL_DEFAULT_REVISION), 2357 DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0), 2358 DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0), 2359 DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0), 2360 DEFINE_PROP_UINT32("ram_size_mb", PCIQXLDevice, ram_size_mb, -1), 2361 DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram32_size_mb, -1), 2362 DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1), 2363 DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 16), 2364 DEFINE_PROP_INT32("surfaces", PCIQXLDevice, ssd.num_surfaces, 1024), 2365 #if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */ 2366 DEFINE_PROP_UINT16("max_outputs", PCIQXLDevice, max_outputs, 0), 2367 #endif 2368 DEFINE_PROP_END_OF_LIST(), 2369 }; 2370 2371 static void qxl_pci_class_init(ObjectClass *klass, void *data) 2372 { 2373 DeviceClass *dc = DEVICE_CLASS(klass); 2374 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 2375 2376 k->vendor_id = REDHAT_PCI_VENDOR_ID; 2377 k->device_id = QXL_DEVICE_ID_STABLE; 2378 set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); 2379 dc->reset = qxl_reset_handler; 2380 dc->vmsd = &qxl_vmstate; 2381 dc->props = qxl_properties; 2382 } 2383 2384 static const TypeInfo qxl_pci_type_info = { 2385 .name = TYPE_PCI_QXL, 2386 .parent = TYPE_PCI_DEVICE, 2387 .instance_size = sizeof(PCIQXLDevice), 2388 .abstract = true, 2389 .class_init = qxl_pci_class_init, 2390 }; 2391 2392 static void qxl_primary_class_init(ObjectClass *klass, void *data) 2393 { 2394 DeviceClass *dc = DEVICE_CLASS(klass); 2395 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 2396 2397 k->realize = qxl_realize_primary; 2398 k->romfile = "vgabios-qxl.bin"; 2399 k->class_id = PCI_CLASS_DISPLAY_VGA; 2400 dc->desc = "Spice QXL GPU (primary, vga compatible)"; 2401 dc->hotpluggable = false; 2402 } 2403 2404 static const TypeInfo qxl_primary_info = { 2405 .name = "qxl-vga", 2406 .parent = TYPE_PCI_QXL, 2407 .class_init = qxl_primary_class_init, 2408 }; 2409 2410 static void qxl_secondary_class_init(ObjectClass *klass, void *data) 2411 { 2412 DeviceClass *dc = DEVICE_CLASS(klass); 2413 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 2414 2415 k->realize = qxl_realize_secondary; 2416 k->class_id = PCI_CLASS_DISPLAY_OTHER; 2417 dc->desc = "Spice QXL GPU (secondary)"; 2418 } 2419 2420 static const TypeInfo qxl_secondary_info = { 2421 .name = "qxl", 2422 .parent = TYPE_PCI_QXL, 2423 .class_init = qxl_secondary_class_init, 2424 }; 2425 2426 static void qxl_register_types(void) 2427 { 2428 type_register_static(&qxl_pci_type_info); 2429 type_register_static(&qxl_primary_info); 2430 type_register_static(&qxl_secondary_info); 2431 } 2432 2433 type_init(qxl_register_types) 2434