qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

qxl.c (86144B)


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