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