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