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