Statistics
| Branch: | Revision:

root / hw / display / qxl.c @ 47b43a1f

History | View | Annotate | Download (76.2 kB)

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 <zlib.h>
22

    
23
#include "qemu-common.h"
24
#include "qemu/timer.h"
25
#include "qemu/queue.h"
26
#include "monitor/monitor.h"
27
#include "sysemu/sysemu.h"
28
#include "trace.h"
29

    
30
#include "qxl.h"
31

    
32
/*
33
 * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as
34
 * such can be changed by the guest, so to avoid a guest trigerrable
35
 * abort we just qxl_set_guest_bug and set the return to NULL. Still
36
 * it may happen as a result of emulator bug as well.
37
 */
38
#undef SPICE_RING_PROD_ITEM
39
#define SPICE_RING_PROD_ITEM(qxl, r, ret) {                             \
40
        uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r);           \
41
        if (prod >= ARRAY_SIZE((r)->items)) {                           \
42
            qxl_set_guest_bug(qxl, "SPICE_RING_PROD_ITEM indices mismatch " \
43
                          "%u >= %zu", prod, ARRAY_SIZE((r)->items));   \
44
            ret = NULL;                                                 \
45
        } else {                                                        \
46
            ret = &(r)->items[prod].el;                                 \
47
        }                                                               \
48
    }
49

    
50
#undef SPICE_RING_CONS_ITEM
51
#define SPICE_RING_CONS_ITEM(qxl, r, ret) {                             \
52
        uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r);           \
53
        if (cons >= ARRAY_SIZE((r)->items)) {                           \
54
            qxl_set_guest_bug(qxl, "SPICE_RING_CONS_ITEM indices mismatch " \
55
                          "%u >= %zu", cons, ARRAY_SIZE((r)->items));   \
56
            ret = NULL;                                                 \
57
        } else {                                                        \
58
            ret = &(r)->items[cons].el;                                 \
59
        }                                                               \
60
    }
61

    
62
#undef ALIGN
63
#define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
64

    
65
#define PIXEL_SIZE 0.2936875 //1280x1024 is 14.8" x 11.9" 
66

    
67
#define QXL_MODE(_x, _y, _b, _o)                  \
68
    {   .x_res = _x,                              \
69
        .y_res = _y,                              \
70
        .bits  = _b,                              \
71
        .stride = (_x) * (_b) / 8,                \
72
        .x_mili = PIXEL_SIZE * (_x),              \
73
        .y_mili = PIXEL_SIZE * (_y),              \
74
        .orientation = _o,                        \
75
    }
76

    
77
#define QXL_MODE_16_32(x_res, y_res, orientation) \
78
    QXL_MODE(x_res, y_res, 16, orientation),      \
79
    QXL_MODE(x_res, y_res, 32, orientation)
80

    
81
#define QXL_MODE_EX(x_res, y_res)                 \
82
    QXL_MODE_16_32(x_res, y_res, 0),              \
83
    QXL_MODE_16_32(x_res, y_res, 1)
84

    
85
static QXLMode qxl_modes[] = {
86
    QXL_MODE_EX(640, 480),
87
    QXL_MODE_EX(800, 480),
88
    QXL_MODE_EX(800, 600),
89
    QXL_MODE_EX(832, 624),
90
    QXL_MODE_EX(960, 640),
91
    QXL_MODE_EX(1024, 600),
92
    QXL_MODE_EX(1024, 768),
93
    QXL_MODE_EX(1152, 864),
94
    QXL_MODE_EX(1152, 870),
95
    QXL_MODE_EX(1280, 720),
96
    QXL_MODE_EX(1280, 760),
97
    QXL_MODE_EX(1280, 768),
98
    QXL_MODE_EX(1280, 800),
99
    QXL_MODE_EX(1280, 960),
100
    QXL_MODE_EX(1280, 1024),
101
    QXL_MODE_EX(1360, 768),
102
    QXL_MODE_EX(1366, 768),
103
    QXL_MODE_EX(1400, 1050),
104
    QXL_MODE_EX(1440, 900),
105
    QXL_MODE_EX(1600, 900),
106
    QXL_MODE_EX(1600, 1200),
107
    QXL_MODE_EX(1680, 1050),
108
    QXL_MODE_EX(1920, 1080),
109
    /* these modes need more than 8 MB video memory */
110
    QXL_MODE_EX(1920, 1200),
111
    QXL_MODE_EX(1920, 1440),
112
    QXL_MODE_EX(2048, 1536),
113
    QXL_MODE_EX(2560, 1440),
114
    QXL_MODE_EX(2560, 1600),
115
    /* these modes need more than 16 MB video memory */
116
    QXL_MODE_EX(2560, 2048),
117
    QXL_MODE_EX(2800, 2100),
118
    QXL_MODE_EX(3200, 2400),
119
};
120

    
121
static void qxl_send_events(PCIQXLDevice *d, uint32_t events);
122
static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async);
123
static void qxl_reset_memslots(PCIQXLDevice *d);
124
static void qxl_reset_surfaces(PCIQXLDevice *d);
125
static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
126

    
127
void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...)
128
{
129
    trace_qxl_set_guest_bug(qxl->id);
130
    qxl_send_events(qxl, QXL_INTERRUPT_ERROR);
131
    qxl->guest_bug = 1;
132
    if (qxl->guestdebug) {
133
        va_list ap;
134
        va_start(ap, msg);
135
        fprintf(stderr, "qxl-%d: guest bug: ", qxl->id);
136
        vfprintf(stderr, msg, ap);
137
        fprintf(stderr, "\n");
138
        va_end(ap);
139
    }
140
}
141

    
142
static void qxl_clear_guest_bug(PCIQXLDevice *qxl)
143
{
144
    qxl->guest_bug = 0;
145
}
146

    
147
void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
148
                           struct QXLRect *area, struct QXLRect *dirty_rects,
149
                           uint32_t num_dirty_rects,
150
                           uint32_t clear_dirty_region,
151
                           qxl_async_io async, struct QXLCookie *cookie)
152
{
153
    trace_qxl_spice_update_area(qxl->id, surface_id, area->left, area->right,
154
                                area->top, area->bottom);
155
    trace_qxl_spice_update_area_rest(qxl->id, num_dirty_rects,
156
                                     clear_dirty_region);
157
    if (async == QXL_SYNC) {
158
        qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area,
159
                        dirty_rects, num_dirty_rects, clear_dirty_region);
160
    } else {
161
        assert(cookie != NULL);
162
        spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area,
163
                                    clear_dirty_region, (uintptr_t)cookie);
164
    }
165
}
166

    
167
static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl,
168
                                                    uint32_t id)
169
{
170
    trace_qxl_spice_destroy_surface_wait_complete(qxl->id, id);
171
    qemu_mutex_lock(&qxl->track_lock);
172
    qxl->guest_surfaces.cmds[id] = 0;
173
    qxl->guest_surfaces.count--;
174
    qemu_mutex_unlock(&qxl->track_lock);
175
}
176

    
177
static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
178
                                           qxl_async_io async)
179
{
180
    QXLCookie *cookie;
181

    
182
    trace_qxl_spice_destroy_surface_wait(qxl->id, id, async);
183
    if (async) {
184
        cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
185
                                QXL_IO_DESTROY_SURFACE_ASYNC);
186
        cookie->u.surface_id = id;
187
        spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uintptr_t)cookie);
188
    } else {
189
        qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
190
        qxl_spice_destroy_surface_wait_complete(qxl, id);
191
    }
192
}
193

    
194
static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
195
{
196
    trace_qxl_spice_flush_surfaces_async(qxl->id, qxl->guest_surfaces.count,
197
                                         qxl->num_free_res);
198
    spice_qxl_flush_surfaces_async(&qxl->ssd.qxl,
199
        (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
200
                                  QXL_IO_FLUSH_SURFACES_ASYNC));
201
}
202

    
203
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
204
                               uint32_t count)
205
{
206
    trace_qxl_spice_loadvm_commands(qxl->id, ext, count);
207
    qxl->ssd.worker->loadvm_commands(qxl->ssd.worker, ext, count);
208
}
209

    
210
void qxl_spice_oom(PCIQXLDevice *qxl)
211
{
212
    trace_qxl_spice_oom(qxl->id);
213
    qxl->ssd.worker->oom(qxl->ssd.worker);
214
}
215

    
216
void qxl_spice_reset_memslots(PCIQXLDevice *qxl)
217
{
218
    trace_qxl_spice_reset_memslots(qxl->id);
219
    qxl->ssd.worker->reset_memslots(qxl->ssd.worker);
220
}
221

    
222
static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
223
{
224
    trace_qxl_spice_destroy_surfaces_complete(qxl->id);
225
    qemu_mutex_lock(&qxl->track_lock);
226
    memset(qxl->guest_surfaces.cmds, 0,
227
           sizeof(qxl->guest_surfaces.cmds) * qxl->ssd.num_surfaces);
228
    qxl->guest_surfaces.count = 0;
229
    qemu_mutex_unlock(&qxl->track_lock);
230
}
231

    
232
static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
233
{
234
    trace_qxl_spice_destroy_surfaces(qxl->id, async);
235
    if (async) {
236
        spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl,
237
                (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
238
                                          QXL_IO_DESTROY_ALL_SURFACES_ASYNC));
239
    } else {
240
        qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
241
        qxl_spice_destroy_surfaces_complete(qxl);
242
    }
243
}
244

    
245
static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay)
246
{
247
    trace_qxl_spice_monitors_config(qxl->id);
248
    if (replay) {
249
        /*
250
         * don't use QXL_COOKIE_TYPE_IO:
251
         *  - we are not running yet (post_load), we will assert
252
         *    in send_events
253
         *  - this is not a guest io, but a reply, so async_io isn't set.
254
         */
255
        spice_qxl_monitors_config_async(&qxl->ssd.qxl,
256
                qxl->guest_monitors_config,
257
                MEMSLOT_GROUP_GUEST,
258
                (uintptr_t)qxl_cookie_new(
259
                    QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
260
                    0));
261
    } else {
262
        qxl->guest_monitors_config = qxl->ram->monitors_config;
263
        spice_qxl_monitors_config_async(&qxl->ssd.qxl,
264
                qxl->ram->monitors_config,
265
                MEMSLOT_GROUP_GUEST,
266
                (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
267
                                          QXL_IO_MONITORS_CONFIG_ASYNC));
268
    }
269
}
270

    
271
void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
272
{
273
    trace_qxl_spice_reset_image_cache(qxl->id);
274
    qxl->ssd.worker->reset_image_cache(qxl->ssd.worker);
275
}
276

    
277
void qxl_spice_reset_cursor(PCIQXLDevice *qxl)
278
{
279
    trace_qxl_spice_reset_cursor(qxl->id);
280
    qxl->ssd.worker->reset_cursor(qxl->ssd.worker);
281
    qemu_mutex_lock(&qxl->track_lock);
282
    qxl->guest_cursor = 0;
283
    qemu_mutex_unlock(&qxl->track_lock);
284
    if (qxl->ssd.cursor) {
285
        cursor_put(qxl->ssd.cursor);
286
    }
287
    qxl->ssd.cursor = cursor_builtin_hidden();
288
}
289

    
290

    
291
static inline uint32_t msb_mask(uint32_t val)
292
{
293
    uint32_t mask;
294

    
295
    do {
296
        mask = ~(val - 1) & val;
297
        val &= ~mask;
298
    } while (mask < val);
299

    
300
    return mask;
301
}
302

    
303
static ram_addr_t qxl_rom_size(void)
304
{
305
    uint32_t required_rom_size = sizeof(QXLRom) + sizeof(QXLModes) +
306
                                 sizeof(qxl_modes);
307
    uint32_t rom_size = 8192; /* two pages */
308

    
309
    required_rom_size = MAX(required_rom_size, TARGET_PAGE_SIZE);
310
    required_rom_size = msb_mask(required_rom_size * 2 - 1);
311
    assert(required_rom_size <= rom_size);
312
    return rom_size;
313
}
314

    
315
static void init_qxl_rom(PCIQXLDevice *d)
316
{
317
    QXLRom *rom = memory_region_get_ram_ptr(&d->rom_bar);
318
    QXLModes *modes = (QXLModes *)(rom + 1);
319
    uint32_t ram_header_size;
320
    uint32_t surface0_area_size;
321
    uint32_t num_pages;
322
    uint32_t fb;
323
    int i, n;
324

    
325
    memset(rom, 0, d->rom_size);
326

    
327
    rom->magic         = cpu_to_le32(QXL_ROM_MAGIC);
328
    rom->id            = cpu_to_le32(d->id);
329
    rom->log_level     = cpu_to_le32(d->guestdebug);
330
    rom->modes_offset  = cpu_to_le32(sizeof(QXLRom));
331

    
332
    rom->slot_gen_bits = MEMSLOT_GENERATION_BITS;
333
    rom->slot_id_bits  = MEMSLOT_SLOT_BITS;
334
    rom->slots_start   = 1;
335
    rom->slots_end     = NUM_MEMSLOTS - 1;
336
    rom->n_surfaces    = cpu_to_le32(d->ssd.num_surfaces);
337

    
338
    for (i = 0, n = 0; i < ARRAY_SIZE(qxl_modes); i++) {
339
        fb = qxl_modes[i].y_res * qxl_modes[i].stride;
340
        if (fb > d->vgamem_size) {
341
            continue;
342
        }
343
        modes->modes[n].id          = cpu_to_le32(i);
344
        modes->modes[n].x_res       = cpu_to_le32(qxl_modes[i].x_res);
345
        modes->modes[n].y_res       = cpu_to_le32(qxl_modes[i].y_res);
346
        modes->modes[n].bits        = cpu_to_le32(qxl_modes[i].bits);
347
        modes->modes[n].stride      = cpu_to_le32(qxl_modes[i].stride);
348
        modes->modes[n].x_mili      = cpu_to_le32(qxl_modes[i].x_mili);
349
        modes->modes[n].y_mili      = cpu_to_le32(qxl_modes[i].y_mili);
350
        modes->modes[n].orientation = cpu_to_le32(qxl_modes[i].orientation);
351
        n++;
352
    }
353
    modes->n_modes     = cpu_to_le32(n);
354

    
355
    ram_header_size    = ALIGN(sizeof(QXLRam), 4096);
356
    surface0_area_size = ALIGN(d->vgamem_size, 4096);
357
    num_pages          = d->vga.vram_size;
358
    num_pages         -= ram_header_size;
359
    num_pages         -= surface0_area_size;
360
    num_pages          = num_pages / TARGET_PAGE_SIZE;
361

    
362
    rom->draw_area_offset   = cpu_to_le32(0);
363
    rom->surface0_area_size = cpu_to_le32(surface0_area_size);
364
    rom->pages_offset       = cpu_to_le32(surface0_area_size);
365
    rom->num_pages          = cpu_to_le32(num_pages);
366
    rom->ram_header_offset  = cpu_to_le32(d->vga.vram_size - ram_header_size);
367

    
368
    d->shadow_rom = *rom;
369
    d->rom        = rom;
370
    d->modes      = modes;
371
}
372

    
373
static void init_qxl_ram(PCIQXLDevice *d)
374
{
375
    uint8_t *buf;
376
    uint64_t *item;
377

    
378
    buf = d->vga.vram_ptr;
379
    d->ram = (QXLRam *)(buf + le32_to_cpu(d->shadow_rom.ram_header_offset));
380
    d->ram->magic       = cpu_to_le32(QXL_RAM_MAGIC);
381
    d->ram->int_pending = cpu_to_le32(0);
382
    d->ram->int_mask    = cpu_to_le32(0);
383
    d->ram->update_surface = 0;
384
    SPICE_RING_INIT(&d->ram->cmd_ring);
385
    SPICE_RING_INIT(&d->ram->cursor_ring);
386
    SPICE_RING_INIT(&d->ram->release_ring);
387
    SPICE_RING_PROD_ITEM(d, &d->ram->release_ring, item);
388
    assert(item);
389
    *item = 0;
390
    qxl_ring_set_dirty(d);
391
}
392

    
393
/* can be called from spice server thread context */
394
static void qxl_set_dirty(MemoryRegion *mr, ram_addr_t addr, ram_addr_t end)
395
{
396
    memory_region_set_dirty(mr, addr, end - addr);
397
}
398

    
399
static void qxl_rom_set_dirty(PCIQXLDevice *qxl)
400
{
401
    qxl_set_dirty(&qxl->rom_bar, 0, qxl->rom_size);
402
}
403

    
404
/* called from spice server thread context only */
405
static void qxl_ram_set_dirty(PCIQXLDevice *qxl, void *ptr)
406
{
407
    void *base = qxl->vga.vram_ptr;
408
    intptr_t offset;
409

    
410
    offset = ptr - base;
411
    offset &= ~(TARGET_PAGE_SIZE-1);
412
    assert(offset < qxl->vga.vram_size);
413
    qxl_set_dirty(&qxl->vga.vram, offset, offset + TARGET_PAGE_SIZE);
414
}
415

    
416
/* can be called from spice server thread context */
417
static void qxl_ring_set_dirty(PCIQXLDevice *qxl)
418
{
419
    ram_addr_t addr = qxl->shadow_rom.ram_header_offset;
420
    ram_addr_t end  = qxl->vga.vram_size;
421
    qxl_set_dirty(&qxl->vga.vram, addr, end);
422
}
423

    
424
/*
425
 * keep track of some command state, for savevm/loadvm.
426
 * called from spice server thread context only
427
 */
428
static int qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext)
429
{
430
    switch (le32_to_cpu(ext->cmd.type)) {
431
    case QXL_CMD_SURFACE:
432
    {
433
        QXLSurfaceCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
434

    
435
        if (!cmd) {
436
            return 1;
437
        }
438
        uint32_t id = le32_to_cpu(cmd->surface_id);
439

    
440
        if (id >= qxl->ssd.num_surfaces) {
441
            qxl_set_guest_bug(qxl, "QXL_CMD_SURFACE id %d >= %d", id,
442
                              qxl->ssd.num_surfaces);
443
            return 1;
444
        }
445
        if (cmd->type == QXL_SURFACE_CMD_CREATE &&
446
            (cmd->u.surface_create.stride & 0x03) != 0) {
447
            qxl_set_guest_bug(qxl, "QXL_CMD_SURFACE stride = %d %% 4 != 0\n",
448
                              cmd->u.surface_create.stride);
449
            return 1;
450
        }
451
        qemu_mutex_lock(&qxl->track_lock);
452
        if (cmd->type == QXL_SURFACE_CMD_CREATE) {
453
            qxl->guest_surfaces.cmds[id] = ext->cmd.data;
454
            qxl->guest_surfaces.count++;
455
            if (qxl->guest_surfaces.max < qxl->guest_surfaces.count)
456
                qxl->guest_surfaces.max = qxl->guest_surfaces.count;
457
        }
458
        if (cmd->type == QXL_SURFACE_CMD_DESTROY) {
459
            qxl->guest_surfaces.cmds[id] = 0;
460
            qxl->guest_surfaces.count--;
461
        }
462
        qemu_mutex_unlock(&qxl->track_lock);
463
        break;
464
    }
465
    case QXL_CMD_CURSOR:
466
    {
467
        QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
468

    
469
        if (!cmd) {
470
            return 1;
471
        }
472
        if (cmd->type == QXL_CURSOR_SET) {
473
            qemu_mutex_lock(&qxl->track_lock);
474
            qxl->guest_cursor = ext->cmd.data;
475
            qemu_mutex_unlock(&qxl->track_lock);
476
        }
477
        break;
478
    }
479
    }
480
    return 0;
481
}
482

    
483
/* spice display interface callbacks */
484

    
485
static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker)
486
{
487
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
488

    
489
    trace_qxl_interface_attach_worker(qxl->id);
490
    qxl->ssd.worker = qxl_worker;
491
}
492

    
493
static void interface_set_compression_level(QXLInstance *sin, int level)
494
{
495
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
496

    
497
    trace_qxl_interface_set_compression_level(qxl->id, level);
498
    qxl->shadow_rom.compression_level = cpu_to_le32(level);
499
    qxl->rom->compression_level = cpu_to_le32(level);
500
    qxl_rom_set_dirty(qxl);
501
}
502

    
503
static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
504
{
505
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
506

    
507
    trace_qxl_interface_set_mm_time(qxl->id, mm_time);
508
    qxl->shadow_rom.mm_clock = cpu_to_le32(mm_time);
509
    qxl->rom->mm_clock = cpu_to_le32(mm_time);
510
    qxl_rom_set_dirty(qxl);
511
}
512

    
513
static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
514
{
515
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
516

    
517
    trace_qxl_interface_get_init_info(qxl->id);
518
    info->memslot_gen_bits = MEMSLOT_GENERATION_BITS;
519
    info->memslot_id_bits = MEMSLOT_SLOT_BITS;
520
    info->num_memslots = NUM_MEMSLOTS;
521
    info->num_memslots_groups = NUM_MEMSLOTS_GROUPS;
522
    info->internal_groupslot_id = 0;
523
    info->qxl_ram_size = le32_to_cpu(qxl->shadow_rom.num_pages) << TARGET_PAGE_BITS;
524
    info->n_surfaces = qxl->ssd.num_surfaces;
525
}
526

    
527
static const char *qxl_mode_to_string(int mode)
528
{
529
    switch (mode) {
530
    case QXL_MODE_COMPAT:
531
        return "compat";
532
    case QXL_MODE_NATIVE:
533
        return "native";
534
    case QXL_MODE_UNDEFINED:
535
        return "undefined";
536
    case QXL_MODE_VGA:
537
        return "vga";
538
    }
539
    return "INVALID";
540
}
541

    
542
static const char *io_port_to_string(uint32_t io_port)
543
{
544
    if (io_port >= QXL_IO_RANGE_SIZE) {
545
        return "out of range";
546
    }
547
    static const char *io_port_to_string[QXL_IO_RANGE_SIZE + 1] = {
548
        [QXL_IO_NOTIFY_CMD]             = "QXL_IO_NOTIFY_CMD",
549
        [QXL_IO_NOTIFY_CURSOR]          = "QXL_IO_NOTIFY_CURSOR",
550
        [QXL_IO_UPDATE_AREA]            = "QXL_IO_UPDATE_AREA",
551
        [QXL_IO_UPDATE_IRQ]             = "QXL_IO_UPDATE_IRQ",
552
        [QXL_IO_NOTIFY_OOM]             = "QXL_IO_NOTIFY_OOM",
553
        [QXL_IO_RESET]                  = "QXL_IO_RESET",
554
        [QXL_IO_SET_MODE]               = "QXL_IO_SET_MODE",
555
        [QXL_IO_LOG]                    = "QXL_IO_LOG",
556
        [QXL_IO_MEMSLOT_ADD]            = "QXL_IO_MEMSLOT_ADD",
557
        [QXL_IO_MEMSLOT_DEL]            = "QXL_IO_MEMSLOT_DEL",
558
        [QXL_IO_DETACH_PRIMARY]         = "QXL_IO_DETACH_PRIMARY",
559
        [QXL_IO_ATTACH_PRIMARY]         = "QXL_IO_ATTACH_PRIMARY",
560
        [QXL_IO_CREATE_PRIMARY]         = "QXL_IO_CREATE_PRIMARY",
561
        [QXL_IO_DESTROY_PRIMARY]        = "QXL_IO_DESTROY_PRIMARY",
562
        [QXL_IO_DESTROY_SURFACE_WAIT]   = "QXL_IO_DESTROY_SURFACE_WAIT",
563
        [QXL_IO_DESTROY_ALL_SURFACES]   = "QXL_IO_DESTROY_ALL_SURFACES",
564
        [QXL_IO_UPDATE_AREA_ASYNC]      = "QXL_IO_UPDATE_AREA_ASYNC",
565
        [QXL_IO_MEMSLOT_ADD_ASYNC]      = "QXL_IO_MEMSLOT_ADD_ASYNC",
566
        [QXL_IO_CREATE_PRIMARY_ASYNC]   = "QXL_IO_CREATE_PRIMARY_ASYNC",
567
        [QXL_IO_DESTROY_PRIMARY_ASYNC]  = "QXL_IO_DESTROY_PRIMARY_ASYNC",
568
        [QXL_IO_DESTROY_SURFACE_ASYNC]  = "QXL_IO_DESTROY_SURFACE_ASYNC",
569
        [QXL_IO_DESTROY_ALL_SURFACES_ASYNC]
570
                                        = "QXL_IO_DESTROY_ALL_SURFACES_ASYNC",
571
        [QXL_IO_FLUSH_SURFACES_ASYNC]   = "QXL_IO_FLUSH_SURFACES_ASYNC",
572
        [QXL_IO_FLUSH_RELEASE]          = "QXL_IO_FLUSH_RELEASE",
573
        [QXL_IO_MONITORS_CONFIG_ASYNC]  = "QXL_IO_MONITORS_CONFIG_ASYNC",
574
    };
575
    return io_port_to_string[io_port];
576
}
577

    
578
/* called from spice server thread context only */
579
static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
580
{
581
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
582
    SimpleSpiceUpdate *update;
583
    QXLCommandRing *ring;
584
    QXLCommand *cmd;
585
    int notify, ret;
586

    
587
    trace_qxl_ring_command_check(qxl->id, qxl_mode_to_string(qxl->mode));
588

    
589
    switch (qxl->mode) {
590
    case QXL_MODE_VGA:
591
        ret = false;
592
        qemu_mutex_lock(&qxl->ssd.lock);
593
        update = QTAILQ_FIRST(&qxl->ssd.updates);
594
        if (update != NULL) {
595
            QTAILQ_REMOVE(&qxl->ssd.updates, update, next);
596
            *ext = update->ext;
597
            ret = true;
598
        }
599
        qemu_mutex_unlock(&qxl->ssd.lock);
600
        if (ret) {
601
            trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
602
            qxl_log_command(qxl, "vga", ext);
603
        }
604
        return ret;
605
    case QXL_MODE_COMPAT:
606
    case QXL_MODE_NATIVE:
607
    case QXL_MODE_UNDEFINED:
608
        ring = &qxl->ram->cmd_ring;
609
        if (qxl->guest_bug || SPICE_RING_IS_EMPTY(ring)) {
610
            return false;
611
        }
612
        SPICE_RING_CONS_ITEM(qxl, ring, cmd);
613
        if (!cmd) {
614
            return false;
615
        }
616
        ext->cmd      = *cmd;
617
        ext->group_id = MEMSLOT_GROUP_GUEST;
618
        ext->flags    = qxl->cmdflags;
619
        SPICE_RING_POP(ring, notify);
620
        qxl_ring_set_dirty(qxl);
621
        if (notify) {
622
            qxl_send_events(qxl, QXL_INTERRUPT_DISPLAY);
623
        }
624
        qxl->guest_primary.commands++;
625
        qxl_track_command(qxl, ext);
626
        qxl_log_command(qxl, "cmd", ext);
627
        trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
628
        return true;
629
    default:
630
        return false;
631
    }
632
}
633

    
634
/* called from spice server thread context only */
635
static int interface_req_cmd_notification(QXLInstance *sin)
636
{
637
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
638
    int wait = 1;
639

    
640
    trace_qxl_ring_command_req_notification(qxl->id);
641
    switch (qxl->mode) {
642
    case QXL_MODE_COMPAT:
643
    case QXL_MODE_NATIVE:
644
    case QXL_MODE_UNDEFINED:
645
        SPICE_RING_CONS_WAIT(&qxl->ram->cmd_ring, wait);
646
        qxl_ring_set_dirty(qxl);
647
        break;
648
    default:
649
        /* nothing */
650
        break;
651
    }
652
    return wait;
653
}
654

    
655
/* called from spice server thread context only */
656
static inline void qxl_push_free_res(PCIQXLDevice *d, int flush)
657
{
658
    QXLReleaseRing *ring = &d->ram->release_ring;
659
    uint64_t *item;
660
    int notify;
661

    
662
#define QXL_FREE_BUNCH_SIZE 32
663

    
664
    if (ring->prod - ring->cons + 1 == ring->num_items) {
665
        /* ring full -- can't push */
666
        return;
667
    }
668
    if (!flush && d->oom_running) {
669
        /* collect everything from oom handler before pushing */
670
        return;
671
    }
672
    if (!flush && d->num_free_res < QXL_FREE_BUNCH_SIZE) {
673
        /* collect a bit more before pushing */
674
        return;
675
    }
676

    
677
    SPICE_RING_PUSH(ring, notify);
678
    trace_qxl_ring_res_push(d->id, qxl_mode_to_string(d->mode),
679
           d->guest_surfaces.count, d->num_free_res,
680
           d->last_release, notify ? "yes" : "no");
681
    trace_qxl_ring_res_push_rest(d->id, ring->prod - ring->cons,
682
           ring->num_items, ring->prod, ring->cons);
683
    if (notify) {
684
        qxl_send_events(d, QXL_INTERRUPT_DISPLAY);
685
    }
686
    SPICE_RING_PROD_ITEM(d, ring, item);
687
    if (!item) {
688
        return;
689
    }
690
    *item = 0;
691
    d->num_free_res = 0;
692
    d->last_release = NULL;
693
    qxl_ring_set_dirty(d);
694
}
695

    
696
/* called from spice server thread context only */
697
static void interface_release_resource(QXLInstance *sin,
698
                                       struct QXLReleaseInfoExt ext)
699
{
700
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
701
    QXLReleaseRing *ring;
702
    uint64_t *item, id;
703

    
704
    if (ext.group_id == MEMSLOT_GROUP_HOST) {
705
        /* host group -> vga mode update request */
706
        qemu_spice_destroy_update(&qxl->ssd, (void *)(intptr_t)ext.info->id);
707
        return;
708
    }
709

    
710
    /*
711
     * ext->info points into guest-visible memory
712
     * pci bar 0, $command.release_info
713
     */
714
    ring = &qxl->ram->release_ring;
715
    SPICE_RING_PROD_ITEM(qxl, ring, item);
716
    if (!item) {
717
        return;
718
    }
719
    if (*item == 0) {
720
        /* stick head into the ring */
721
        id = ext.info->id;
722
        ext.info->next = 0;
723
        qxl_ram_set_dirty(qxl, &ext.info->next);
724
        *item = id;
725
        qxl_ring_set_dirty(qxl);
726
    } else {
727
        /* append item to the list */
728
        qxl->last_release->next = ext.info->id;
729
        qxl_ram_set_dirty(qxl, &qxl->last_release->next);
730
        ext.info->next = 0;
731
        qxl_ram_set_dirty(qxl, &ext.info->next);
732
    }
733
    qxl->last_release = ext.info;
734
    qxl->num_free_res++;
735
    trace_qxl_ring_res_put(qxl->id, qxl->num_free_res);
736
    qxl_push_free_res(qxl, 0);
737
}
738

    
739
/* called from spice server thread context only */
740
static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext)
741
{
742
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
743
    QXLCursorRing *ring;
744
    QXLCommand *cmd;
745
    int notify;
746

    
747
    trace_qxl_ring_cursor_check(qxl->id, qxl_mode_to_string(qxl->mode));
748

    
749
    switch (qxl->mode) {
750
    case QXL_MODE_COMPAT:
751
    case QXL_MODE_NATIVE:
752
    case QXL_MODE_UNDEFINED:
753
        ring = &qxl->ram->cursor_ring;
754
        if (SPICE_RING_IS_EMPTY(ring)) {
755
            return false;
756
        }
757
        SPICE_RING_CONS_ITEM(qxl, ring, cmd);
758
        if (!cmd) {
759
            return false;
760
        }
761
        ext->cmd      = *cmd;
762
        ext->group_id = MEMSLOT_GROUP_GUEST;
763
        ext->flags    = qxl->cmdflags;
764
        SPICE_RING_POP(ring, notify);
765
        qxl_ring_set_dirty(qxl);
766
        if (notify) {
767
            qxl_send_events(qxl, QXL_INTERRUPT_CURSOR);
768
        }
769
        qxl->guest_primary.commands++;
770
        qxl_track_command(qxl, ext);
771
        qxl_log_command(qxl, "csr", ext);
772
        if (qxl->id == 0) {
773
            qxl_render_cursor(qxl, ext);
774
        }
775
        trace_qxl_ring_cursor_get(qxl->id, qxl_mode_to_string(qxl->mode));
776
        return true;
777
    default:
778
        return false;
779
    }
780
}
781

    
782
/* called from spice server thread context only */
783
static int interface_req_cursor_notification(QXLInstance *sin)
784
{
785
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
786
    int wait = 1;
787

    
788
    trace_qxl_ring_cursor_req_notification(qxl->id);
789
    switch (qxl->mode) {
790
    case QXL_MODE_COMPAT:
791
    case QXL_MODE_NATIVE:
792
    case QXL_MODE_UNDEFINED:
793
        SPICE_RING_CONS_WAIT(&qxl->ram->cursor_ring, wait);
794
        qxl_ring_set_dirty(qxl);
795
        break;
796
    default:
797
        /* nothing */
798
        break;
799
    }
800
    return wait;
801
}
802

    
803
/* called from spice server thread context */
804
static void interface_notify_update(QXLInstance *sin, uint32_t update_id)
805
{
806
    /*
807
     * Called by spice-server as a result of a QXL_CMD_UPDATE which is not in
808
     * use by xf86-video-qxl and is defined out in the qxl windows driver.
809
     * Probably was at some earlier version that is prior to git start (2009),
810
     * and is still guest trigerrable.
811
     */
812
    fprintf(stderr, "%s: deprecated\n", __func__);
813
}
814

    
815
/* called from spice server thread context only */
816
static int interface_flush_resources(QXLInstance *sin)
817
{
818
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
819
    int ret;
820

    
821
    ret = qxl->num_free_res;
822
    if (ret) {
823
        qxl_push_free_res(qxl, 1);
824
    }
825
    return ret;
826
}
827

    
828
static void qxl_create_guest_primary_complete(PCIQXLDevice *d);
829

    
830
/* called from spice server thread context only */
831
static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
832
{
833
    uint32_t current_async;
834

    
835
    qemu_mutex_lock(&qxl->async_lock);
836
    current_async = qxl->current_async;
837
    qxl->current_async = QXL_UNDEFINED_IO;
838
    qemu_mutex_unlock(&qxl->async_lock);
839

    
840
    trace_qxl_interface_async_complete_io(qxl->id, current_async, cookie);
841
    if (!cookie) {
842
        fprintf(stderr, "qxl: %s: error, cookie is NULL\n", __func__);
843
        return;
844
    }
845
    if (cookie && current_async != cookie->io) {
846
        fprintf(stderr,
847
                "qxl: %s: error: current_async = %d != %"
848
                PRId64 " = cookie->io\n", __func__, current_async, cookie->io);
849
    }
850
    switch (current_async) {
851
    case QXL_IO_MEMSLOT_ADD_ASYNC:
852
    case QXL_IO_DESTROY_PRIMARY_ASYNC:
853
    case QXL_IO_UPDATE_AREA_ASYNC:
854
    case QXL_IO_FLUSH_SURFACES_ASYNC:
855
    case QXL_IO_MONITORS_CONFIG_ASYNC:
856
        break;
857
    case QXL_IO_CREATE_PRIMARY_ASYNC:
858
        qxl_create_guest_primary_complete(qxl);
859
        break;
860
    case QXL_IO_DESTROY_ALL_SURFACES_ASYNC:
861
        qxl_spice_destroy_surfaces_complete(qxl);
862
        break;
863
    case QXL_IO_DESTROY_SURFACE_ASYNC:
864
        qxl_spice_destroy_surface_wait_complete(qxl, cookie->u.surface_id);
865
        break;
866
    default:
867
        fprintf(stderr, "qxl: %s: unexpected current_async %d\n", __func__,
868
                current_async);
869
    }
870
    qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
871
}
872

    
873
/* called from spice server thread context only */
874
static void interface_update_area_complete(QXLInstance *sin,
875
        uint32_t surface_id,
876
        QXLRect *dirty, uint32_t num_updated_rects)
877
{
878
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
879
    int i;
880
    int qxl_i;
881

    
882
    qemu_mutex_lock(&qxl->ssd.lock);
883
    if (surface_id != 0 || !qxl->render_update_cookie_num) {
884
        qemu_mutex_unlock(&qxl->ssd.lock);
885
        return;
886
    }
887
    trace_qxl_interface_update_area_complete(qxl->id, surface_id, dirty->left,
888
            dirty->right, dirty->top, dirty->bottom);
889
    trace_qxl_interface_update_area_complete_rest(qxl->id, num_updated_rects);
890
    if (qxl->num_dirty_rects + num_updated_rects > QXL_NUM_DIRTY_RECTS) {
891
        /*
892
         * overflow - treat this as a full update. Not expected to be common.
893
         */
894
        trace_qxl_interface_update_area_complete_overflow(qxl->id,
895
                                                          QXL_NUM_DIRTY_RECTS);
896
        qxl->guest_primary.resized = 1;
897
    }
898
    if (qxl->guest_primary.resized) {
899
        /*
900
         * Don't bother copying or scheduling the bh since we will flip
901
         * the whole area anyway on completion of the update_area async call
902
         */
903
        qemu_mutex_unlock(&qxl->ssd.lock);
904
        return;
905
    }
906
    qxl_i = qxl->num_dirty_rects;
907
    for (i = 0; i < num_updated_rects; i++) {
908
        qxl->dirty[qxl_i++] = dirty[i];
909
    }
910
    qxl->num_dirty_rects += num_updated_rects;
911
    trace_qxl_interface_update_area_complete_schedule_bh(qxl->id,
912
                                                         qxl->num_dirty_rects);
913
    qemu_bh_schedule(qxl->update_area_bh);
914
    qemu_mutex_unlock(&qxl->ssd.lock);
915
}
916

    
917
/* called from spice server thread context only */
918
static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
919
{
920
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
921
    QXLCookie *cookie = (QXLCookie *)(uintptr_t)cookie_token;
922

    
923
    switch (cookie->type) {
924
    case QXL_COOKIE_TYPE_IO:
925
        interface_async_complete_io(qxl, cookie);
926
        g_free(cookie);
927
        break;
928
    case QXL_COOKIE_TYPE_RENDER_UPDATE_AREA:
929
        qxl_render_update_area_done(qxl, cookie);
930
        break;
931
    case QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG:
932
        break;
933
    default:
934
        fprintf(stderr, "qxl: %s: unexpected cookie type %d\n",
935
                __func__, cookie->type);
936
        g_free(cookie);
937
    }
938
}
939

    
940
/* called from spice server thread context only */
941
static void interface_set_client_capabilities(QXLInstance *sin,
942
                                              uint8_t client_present,
943
                                              uint8_t caps[58])
944
{
945
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
946

    
947
    if (qxl->revision < 4) {
948
        trace_qxl_set_client_capabilities_unsupported_by_revision(qxl->id,
949
                                                              qxl->revision);
950
        return;
951
    }
952

    
953
    if (runstate_check(RUN_STATE_INMIGRATE) ||
954
        runstate_check(RUN_STATE_POSTMIGRATE)) {
955
        return;
956
    }
957

    
958
    qxl->shadow_rom.client_present = client_present;
959
    memcpy(qxl->shadow_rom.client_capabilities, caps,
960
           sizeof(qxl->shadow_rom.client_capabilities));
961
    qxl->rom->client_present = client_present;
962
    memcpy(qxl->rom->client_capabilities, caps,
963
           sizeof(qxl->rom->client_capabilities));
964
    qxl_rom_set_dirty(qxl);
965

    
966
    qxl_send_events(qxl, QXL_INTERRUPT_CLIENT);
967
}
968

    
969
static uint32_t qxl_crc32(const uint8_t *p, unsigned len)
970
{
971
    /*
972
     * zlib xors the seed with 0xffffffff, and xors the result
973
     * again with 0xffffffff; Both are not done with linux's crc32,
974
     * which we want to be compatible with, so undo that.
975
     */
976
    return crc32(0xffffffff, p, len) ^ 0xffffffff;
977
}
978

    
979
/* called from main context only */
980
static int interface_client_monitors_config(QXLInstance *sin,
981
                                        VDAgentMonitorsConfig *monitors_config)
982
{
983
    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
984
    QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);
985
    int i;
986

    
987
    if (qxl->revision < 4) {
988
        trace_qxl_client_monitors_config_unsupported_by_device(qxl->id,
989
                                                               qxl->revision);
990
        return 0;
991
    }
992
    /*
993
     * Older windows drivers set int_mask to 0 when their ISR is called,
994
     * then later set it to ~0. So it doesn't relate to the actual interrupts
995
     * handled. However, they are old, so clearly they don't support this
996
     * interrupt
997
     */
998
    if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 ||
999
        !(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) {
1000
        trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id,
1001
                                                            qxl->ram->int_mask,
1002
                                                            monitors_config);
1003
        return 0;
1004
    }
1005
    if (!monitors_config) {
1006
        return 1;
1007
    }
1008
    memset(&rom->client_monitors_config, 0,
1009
           sizeof(rom->client_monitors_config));
1010
    rom->client_monitors_config.count = monitors_config->num_of_monitors;
1011
    /* monitors_config->flags ignored */
1012
    if (rom->client_monitors_config.count >=
1013
            ARRAY_SIZE(rom->client_monitors_config.heads)) {
1014
        trace_qxl_client_monitors_config_capped(qxl->id,
1015
                                monitors_config->num_of_monitors,
1016
                                ARRAY_SIZE(rom->client_monitors_config.heads));
1017
        rom->client_monitors_config.count =
1018
            ARRAY_SIZE(rom->client_monitors_config.heads);
1019
    }
1020
    for (i = 0 ; i < rom->client_monitors_config.count ; ++i) {
1021
        VDAgentMonConfig *monitor = &monitors_config->monitors[i];
1022
        QXLURect *rect = &rom->client_monitors_config.heads[i];
1023
        /* monitor->depth ignored */
1024
        rect->left = monitor->x;
1025
        rect->top = monitor->y;
1026
        rect->right = monitor->x + monitor->width;
1027
        rect->bottom = monitor->y + monitor->height;
1028
    }
1029
    rom->client_monitors_config_crc = qxl_crc32(
1030
            (const uint8_t *)&rom->client_monitors_config,
1031
            sizeof(rom->client_monitors_config));
1032
    trace_qxl_client_monitors_config_crc(qxl->id,
1033
            sizeof(rom->client_monitors_config),
1034
            rom->client_monitors_config_crc);
1035

    
1036
    trace_qxl_interrupt_client_monitors_config(qxl->id,
1037
                        rom->client_monitors_config.count,
1038
                        rom->client_monitors_config.heads);
1039
    qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);
1040
    return 1;
1041
}
1042

    
1043
static const QXLInterface qxl_interface = {
1044
    .base.type               = SPICE_INTERFACE_QXL,
1045
    .base.description        = "qxl gpu",
1046
    .base.major_version      = SPICE_INTERFACE_QXL_MAJOR,
1047
    .base.minor_version      = SPICE_INTERFACE_QXL_MINOR,
1048

    
1049
    .attache_worker          = interface_attach_worker,
1050
    .set_compression_level   = interface_set_compression_level,
1051
    .set_mm_time             = interface_set_mm_time,
1052
    .get_init_info           = interface_get_init_info,
1053

    
1054
    /* the callbacks below are called from spice server thread context */
1055
    .get_command             = interface_get_command,
1056
    .req_cmd_notification    = interface_req_cmd_notification,
1057
    .release_resource        = interface_release_resource,
1058
    .get_cursor_command      = interface_get_cursor_command,
1059
    .req_cursor_notification = interface_req_cursor_notification,
1060
    .notify_update           = interface_notify_update,
1061
    .flush_resources         = interface_flush_resources,
1062
    .async_complete          = interface_async_complete,
1063
    .update_area_complete    = interface_update_area_complete,
1064
    .set_client_capabilities = interface_set_client_capabilities,
1065
    .client_monitors_config = interface_client_monitors_config,
1066
};
1067

    
1068
static void qxl_enter_vga_mode(PCIQXLDevice *d)
1069
{
1070
    if (d->mode == QXL_MODE_VGA) {
1071
        return;
1072
    }
1073
    trace_qxl_enter_vga_mode(d->id);
1074
    qemu_spice_create_host_primary(&d->ssd);
1075
    d->mode = QXL_MODE_VGA;
1076
    vga_dirty_log_start(&d->vga);
1077
    vga_hw_update();
1078
}
1079

    
1080
static void qxl_exit_vga_mode(PCIQXLDevice *d)
1081
{
1082
    if (d->mode != QXL_MODE_VGA) {
1083
        return;
1084
    }
1085
    trace_qxl_exit_vga_mode(d->id);
1086
    vga_dirty_log_stop(&d->vga);
1087
    qxl_destroy_primary(d, QXL_SYNC);
1088
}
1089

    
1090
static void qxl_update_irq(PCIQXLDevice *d)
1091
{
1092
    uint32_t pending = le32_to_cpu(d->ram->int_pending);
1093
    uint32_t mask    = le32_to_cpu(d->ram->int_mask);
1094
    int level = !!(pending & mask);
1095
    qemu_set_irq(d->pci.irq[0], level);
1096
    qxl_ring_set_dirty(d);
1097
}
1098

    
1099
static void qxl_check_state(PCIQXLDevice *d)
1100
{
1101
    QXLRam *ram = d->ram;
1102
    int spice_display_running = qemu_spice_display_is_running(&d->ssd);
1103

    
1104
    assert(!spice_display_running || SPICE_RING_IS_EMPTY(&ram->cmd_ring));
1105
    assert(!spice_display_running || SPICE_RING_IS_EMPTY(&ram->cursor_ring));
1106
}
1107

    
1108
static void qxl_reset_state(PCIQXLDevice *d)
1109
{
1110
    QXLRom *rom = d->rom;
1111

    
1112
    qxl_check_state(d);
1113
    d->shadow_rom.update_id = cpu_to_le32(0);
1114
    *rom = d->shadow_rom;
1115
    qxl_rom_set_dirty(d);
1116
    init_qxl_ram(d);
1117
    d->num_free_res = 0;
1118
    d->last_release = NULL;
1119
    memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty));
1120
}
1121

    
1122
static void qxl_soft_reset(PCIQXLDevice *d)
1123
{
1124
    trace_qxl_soft_reset(d->id);
1125
    qxl_check_state(d);
1126
    qxl_clear_guest_bug(d);
1127
    d->current_async = QXL_UNDEFINED_IO;
1128

    
1129
    if (d->id == 0) {
1130
        qxl_enter_vga_mode(d);
1131
    } else {
1132
        d->mode = QXL_MODE_UNDEFINED;
1133
    }
1134
}
1135

    
1136
static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
1137
{
1138
    trace_qxl_hard_reset(d->id, loadvm);
1139

    
1140
    qxl_spice_reset_cursor(d);
1141
    qxl_spice_reset_image_cache(d);
1142
    qxl_reset_surfaces(d);
1143
    qxl_reset_memslots(d);
1144

    
1145
    /* pre loadvm reset must not touch QXLRam.  This lives in
1146
     * device memory, is migrated together with RAM and thus
1147
     * already loaded at this point */
1148
    if (!loadvm) {
1149
        qxl_reset_state(d);
1150
    }
1151
    qemu_spice_create_host_memslot(&d->ssd);
1152
    qxl_soft_reset(d);
1153
}
1154

    
1155
static void qxl_reset_handler(DeviceState *dev)
1156
{
1157
    PCIQXLDevice *d = DO_UPCAST(PCIQXLDevice, pci.qdev, dev);
1158

    
1159
    qxl_hard_reset(d, 0);
1160
}
1161

    
1162
static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
1163
{
1164
    VGACommonState *vga = opaque;
1165
    PCIQXLDevice *qxl = container_of(vga, PCIQXLDevice, vga);
1166

    
1167
    trace_qxl_io_write_vga(qxl->id, qxl_mode_to_string(qxl->mode), addr, val);
1168
    if (qxl->mode != QXL_MODE_VGA) {
1169
        qxl_destroy_primary(qxl, QXL_SYNC);
1170
        qxl_soft_reset(qxl);
1171
    }
1172
    vga_ioport_write(opaque, addr, val);
1173
}
1174

    
1175
static const MemoryRegionPortio qxl_vga_portio_list[] = {
1176
    { 0x04,  2, 1, .read  = vga_ioport_read,
1177
                   .write = qxl_vga_ioport_write }, /* 3b4 */
1178
    { 0x0a,  1, 1, .read  = vga_ioport_read,
1179
                   .write = qxl_vga_ioport_write }, /* 3ba */
1180
    { 0x10, 16, 1, .read  = vga_ioport_read,
1181
                   .write = qxl_vga_ioport_write }, /* 3c0 */
1182
    { 0x24,  2, 1, .read  = vga_ioport_read,
1183
                   .write = qxl_vga_ioport_write }, /* 3d4 */
1184
    { 0x2a,  1, 1, .read  = vga_ioport_read,
1185
                   .write = qxl_vga_ioport_write }, /* 3da */
1186
    PORTIO_END_OF_LIST(),
1187
};
1188

    
1189
static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
1190
                           qxl_async_io async)
1191
{
1192
    static const int regions[] = {
1193
        QXL_RAM_RANGE_INDEX,
1194
        QXL_VRAM_RANGE_INDEX,
1195
        QXL_VRAM64_RANGE_INDEX,
1196
    };
1197
    uint64_t guest_start;
1198
    uint64_t guest_end;
1199
    int pci_region;
1200
    pcibus_t pci_start;
1201
    pcibus_t pci_end;
1202
    intptr_t virt_start;
1203
    QXLDevMemSlot memslot;
1204
    int i;
1205

    
1206
    guest_start = le64_to_cpu(d->guest_slots[slot_id].slot.mem_start);
1207
    guest_end   = le64_to_cpu(d->guest_slots[slot_id].slot.mem_end);
1208

    
1209
    trace_qxl_memslot_add_guest(d->id, slot_id, guest_start, guest_end);
1210

    
1211
    if (slot_id >= NUM_MEMSLOTS) {
1212
        qxl_set_guest_bug(d, "%s: slot_id >= NUM_MEMSLOTS %d >= %d", __func__,
1213
                      slot_id, NUM_MEMSLOTS);
1214
        return 1;
1215
    }
1216
    if (guest_start > guest_end) {
1217
        qxl_set_guest_bug(d, "%s: guest_start > guest_end 0x%" PRIx64
1218
                         " > 0x%" PRIx64, __func__, guest_start, guest_end);
1219
        return 1;
1220
    }
1221

    
1222
    for (i = 0; i < ARRAY_SIZE(regions); i++) {
1223
        pci_region = regions[i];
1224
        pci_start = d->pci.io_regions[pci_region].addr;
1225
        pci_end = pci_start + d->pci.io_regions[pci_region].size;
1226
        /* mapped? */
1227
        if (pci_start == -1) {
1228
            continue;
1229
        }
1230
        /* start address in range ? */
1231
        if (guest_start < pci_start || guest_start > pci_end) {
1232
            continue;
1233
        }
1234
        /* end address in range ? */
1235
        if (guest_end > pci_end) {
1236
            continue;
1237
        }
1238
        /* passed */
1239
        break;
1240
    }
1241
    if (i == ARRAY_SIZE(regions)) {
1242
        qxl_set_guest_bug(d, "%s: finished loop without match", __func__);
1243
        return 1;
1244
    }
1245

    
1246
    switch (pci_region) {
1247
    case QXL_RAM_RANGE_INDEX:
1248
        virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vga.vram);
1249
        break;
1250
    case QXL_VRAM_RANGE_INDEX:
1251
    case 4 /* vram 64bit */:
1252
        virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vram_bar);
1253
        break;
1254
    default:
1255
        /* should not happen */
1256
        qxl_set_guest_bug(d, "%s: pci_region = %d", __func__, pci_region);
1257
        return 1;
1258
    }
1259

    
1260
    memslot.slot_id = slot_id;
1261
    memslot.slot_group_id = MEMSLOT_GROUP_GUEST; /* guest group */
1262
    memslot.virt_start = virt_start + (guest_start - pci_start);
1263
    memslot.virt_end   = virt_start + (guest_end   - pci_start);
1264
    memslot.addr_delta = memslot.virt_start - delta;
1265
    memslot.generation = d->rom->slot_generation = 0;
1266
    qxl_rom_set_dirty(d);
1267

    
1268
    qemu_spice_add_memslot(&d->ssd, &memslot, async);
1269
    d->guest_slots[slot_id].ptr = (void*)memslot.virt_start;
1270
    d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start;
1271
    d->guest_slots[slot_id].delta = delta;
1272
    d->guest_slots[slot_id].active = 1;
1273
    return 0;
1274
}
1275

    
1276
static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id)
1277
{
1278
    qemu_spice_del_memslot(&d->ssd, MEMSLOT_GROUP_HOST, slot_id);
1279
    d->guest_slots[slot_id].active = 0;
1280
}
1281

    
1282
static void qxl_reset_memslots(PCIQXLDevice *d)
1283
{
1284
    qxl_spice_reset_memslots(d);
1285
    memset(&d->guest_slots, 0, sizeof(d->guest_slots));
1286
}
1287

    
1288
static void qxl_reset_surfaces(PCIQXLDevice *d)
1289
{
1290
    trace_qxl_reset_surfaces(d->id);
1291
    d->mode = QXL_MODE_UNDEFINED;
1292
    qxl_spice_destroy_surfaces(d, QXL_SYNC);
1293
}
1294

    
1295
/* can be also called from spice server thread context */
1296
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
1297
{
1298
    uint64_t phys   = le64_to_cpu(pqxl);
1299
    uint32_t slot   = (phys >> (64 -  8)) & 0xff;
1300
    uint64_t offset = phys & 0xffffffffffff;
1301

    
1302
    switch (group_id) {
1303
    case MEMSLOT_GROUP_HOST:
1304
        return (void *)(intptr_t)offset;
1305
    case MEMSLOT_GROUP_GUEST:
1306
        if (slot >= NUM_MEMSLOTS) {
1307
            qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot,
1308
                              NUM_MEMSLOTS);
1309
            return NULL;
1310
        }
1311
        if (!qxl->guest_slots[slot].active) {
1312
            qxl_set_guest_bug(qxl, "inactive slot %d\n", slot);
1313
            return NULL;
1314
        }
1315
        if (offset < qxl->guest_slots[slot].delta) {
1316
            qxl_set_guest_bug(qxl,
1317
                          "slot %d offset %"PRIu64" < delta %"PRIu64"\n",
1318
                          slot, offset, qxl->guest_slots[slot].delta);
1319
            return NULL;
1320
        }
1321
        offset -= qxl->guest_slots[slot].delta;
1322
        if (offset > qxl->guest_slots[slot].size) {
1323
            qxl_set_guest_bug(qxl,
1324
                          "slot %d offset %"PRIu64" > size %"PRIu64"\n",
1325
                          slot, offset, qxl->guest_slots[slot].size);
1326
            return NULL;
1327
        }
1328
        return qxl->guest_slots[slot].ptr + offset;
1329
    }
1330
    return NULL;
1331
}
1332

    
1333
static void qxl_create_guest_primary_complete(PCIQXLDevice *qxl)
1334
{
1335
    /* for local rendering */
1336
    qxl_render_resize(qxl);
1337
}
1338

    
1339
static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
1340
                                     qxl_async_io async)
1341
{
1342
    QXLDevSurfaceCreate surface;
1343
    QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
1344
    int size;
1345
    int requested_height = le32_to_cpu(sc->height);
1346
    int requested_stride = le32_to_cpu(sc->stride);
1347

    
1348
    size = abs(requested_stride) * requested_height;
1349
    if (size > qxl->vgamem_size) {
1350
        qxl_set_guest_bug(qxl, "%s: requested primary larger then framebuffer"
1351
                               " size", __func__);
1352
        return;
1353
    }
1354

    
1355
    if (qxl->mode == QXL_MODE_NATIVE) {
1356
        qxl_set_guest_bug(qxl, "%s: nop since already in QXL_MODE_NATIVE",
1357
                      __func__);
1358
    }
1359
    qxl_exit_vga_mode(qxl);
1360

    
1361
    surface.format     = le32_to_cpu(sc->format);
1362
    surface.height     = le32_to_cpu(sc->height);
1363
    surface.mem        = le64_to_cpu(sc->mem);
1364
    surface.position   = le32_to_cpu(sc->position);
1365
    surface.stride     = le32_to_cpu(sc->stride);
1366
    surface.width      = le32_to_cpu(sc->width);
1367
    surface.type       = le32_to_cpu(sc->type);
1368
    surface.flags      = le32_to_cpu(sc->flags);
1369
    trace_qxl_create_guest_primary(qxl->id, sc->width, sc->height, sc->mem,
1370
                                   sc->format, sc->position);
1371
    trace_qxl_create_guest_primary_rest(qxl->id, sc->stride, sc->type,
1372
                                        sc->flags);
1373

    
1374
    if ((surface.stride & 0x3) != 0) {
1375
        qxl_set_guest_bug(qxl, "primary surface stride = %d %% 4 != 0",
1376
                          surface.stride);
1377
        return;
1378
    }
1379

    
1380
    surface.mouse_mode = true;
1381
    surface.group_id   = MEMSLOT_GROUP_GUEST;
1382
    if (loadvm) {
1383
        surface.flags |= QXL_SURF_FLAG_KEEP_DATA;
1384
    }
1385

    
1386
    qxl->mode = QXL_MODE_NATIVE;
1387
    qxl->cmdflags = 0;
1388
    qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface, async);
1389

    
1390
    if (async == QXL_SYNC) {
1391
        qxl_create_guest_primary_complete(qxl);
1392
    }
1393
}
1394

    
1395
/* return 1 if surface destoy was initiated (in QXL_ASYNC case) or
1396
 * done (in QXL_SYNC case), 0 otherwise. */
1397
static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
1398
{
1399
    if (d->mode == QXL_MODE_UNDEFINED) {
1400
        return 0;
1401
    }
1402
    trace_qxl_destroy_primary(d->id);
1403
    d->mode = QXL_MODE_UNDEFINED;
1404
    qemu_spice_destroy_primary_surface(&d->ssd, 0, async);
1405
    qxl_spice_reset_cursor(d);
1406
    return 1;
1407
}
1408

    
1409
static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
1410
{
1411
    pcibus_t start = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr;
1412
    pcibus_t end   = d->pci.io_regions[QXL_RAM_RANGE_INDEX].size + start;
1413
    QXLMode *mode = d->modes->modes + modenr;
1414
    uint64_t devmem = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr;
1415
    QXLMemSlot slot = {
1416
        .mem_start = start,
1417
        .mem_end = end
1418
    };
1419
    QXLSurfaceCreate surface = {
1420
        .width      = mode->x_res,
1421
        .height     = mode->y_res,
1422
        .stride     = -mode->x_res * 4,
1423
        .format     = SPICE_SURFACE_FMT_32_xRGB,
1424
        .flags      = loadvm ? QXL_SURF_FLAG_KEEP_DATA : 0,
1425
        .mouse_mode = true,
1426
        .mem        = devmem + d->shadow_rom.draw_area_offset,
1427
    };
1428

    
1429
    trace_qxl_set_mode(d->id, modenr, mode->x_res, mode->y_res, mode->bits,
1430
                       devmem);
1431
    if (!loadvm) {
1432
        qxl_hard_reset(d, 0);
1433
    }
1434

    
1435
    d->guest_slots[0].slot = slot;
1436
    assert(qxl_add_memslot(d, 0, devmem, QXL_SYNC) == 0);
1437

    
1438
    d->guest_primary.surface = surface;
1439
    qxl_create_guest_primary(d, 0, QXL_SYNC);
1440

    
1441
    d->mode = QXL_MODE_COMPAT;
1442
    d->cmdflags = QXL_COMMAND_FLAG_COMPAT;
1443
    if (mode->bits == 16) {
1444
        d->cmdflags |= QXL_COMMAND_FLAG_COMPAT_16BPP;
1445
    }
1446
    d->shadow_rom.mode = cpu_to_le32(modenr);
1447
    d->rom->mode = cpu_to_le32(modenr);
1448
    qxl_rom_set_dirty(d);
1449
}
1450

    
1451
static void ioport_write(void *opaque, hwaddr addr,
1452
                         uint64_t val, unsigned size)
1453
{
1454
    PCIQXLDevice *d = opaque;
1455
    uint32_t io_port = addr;
1456
    qxl_async_io async = QXL_SYNC;
1457
    uint32_t orig_io_port = io_port;
1458

    
1459
    if (d->guest_bug && io_port != QXL_IO_RESET) {
1460
        return;
1461
    }
1462

    
1463
    if (d->revision <= QXL_REVISION_STABLE_V10 &&
1464
        io_port > QXL_IO_FLUSH_RELEASE) {
1465
        qxl_set_guest_bug(d, "unsupported io %d for revision %d\n",
1466
            io_port, d->revision);
1467
        return;
1468
    }
1469

    
1470
    switch (io_port) {
1471
    case QXL_IO_RESET:
1472
    case QXL_IO_SET_MODE:
1473
    case QXL_IO_MEMSLOT_ADD:
1474
    case QXL_IO_MEMSLOT_DEL:
1475
    case QXL_IO_CREATE_PRIMARY:
1476
    case QXL_IO_UPDATE_IRQ:
1477
    case QXL_IO_LOG:
1478
    case QXL_IO_MEMSLOT_ADD_ASYNC:
1479
    case QXL_IO_CREATE_PRIMARY_ASYNC:
1480
        break;
1481
    default:
1482
        if (d->mode != QXL_MODE_VGA) {
1483
            break;
1484
        }
1485
        trace_qxl_io_unexpected_vga_mode(d->id,
1486
            addr, val, io_port_to_string(io_port));
1487
        /* be nice to buggy guest drivers */
1488
        if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
1489
            io_port < QXL_IO_RANGE_SIZE) {
1490
            qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
1491
        }
1492
        return;
1493
    }
1494

    
1495
    /* we change the io_port to avoid ifdeffery in the main switch */
1496
    orig_io_port = io_port;
1497
    switch (io_port) {
1498
    case QXL_IO_UPDATE_AREA_ASYNC:
1499
        io_port = QXL_IO_UPDATE_AREA;
1500
        goto async_common;
1501
    case QXL_IO_MEMSLOT_ADD_ASYNC:
1502
        io_port = QXL_IO_MEMSLOT_ADD;
1503
        goto async_common;
1504
    case QXL_IO_CREATE_PRIMARY_ASYNC:
1505
        io_port = QXL_IO_CREATE_PRIMARY;
1506
        goto async_common;
1507
    case QXL_IO_DESTROY_PRIMARY_ASYNC:
1508
        io_port = QXL_IO_DESTROY_PRIMARY;
1509
        goto async_common;
1510
    case QXL_IO_DESTROY_SURFACE_ASYNC:
1511
        io_port = QXL_IO_DESTROY_SURFACE_WAIT;
1512
        goto async_common;
1513
    case QXL_IO_DESTROY_ALL_SURFACES_ASYNC:
1514
        io_port = QXL_IO_DESTROY_ALL_SURFACES;
1515
        goto async_common;
1516
    case QXL_IO_FLUSH_SURFACES_ASYNC:
1517
    case QXL_IO_MONITORS_CONFIG_ASYNC:
1518
async_common:
1519
        async = QXL_ASYNC;
1520
        qemu_mutex_lock(&d->async_lock);
1521
        if (d->current_async != QXL_UNDEFINED_IO) {
1522
            qxl_set_guest_bug(d, "%d async started before last (%d) complete",
1523
                io_port, d->current_async);
1524
            qemu_mutex_unlock(&d->async_lock);
1525
            return;
1526
        }
1527
        d->current_async = orig_io_port;
1528
        qemu_mutex_unlock(&d->async_lock);
1529
        break;
1530
    default:
1531
        break;
1532
    }
1533
    trace_qxl_io_write(d->id, qxl_mode_to_string(d->mode), addr, val, size,
1534
                       async);
1535

    
1536
    switch (io_port) {
1537
    case QXL_IO_UPDATE_AREA:
1538
    {
1539
        QXLCookie *cookie = NULL;
1540
        QXLRect update = d->ram->update_area;
1541

    
1542
        if (d->ram->update_surface > d->ssd.num_surfaces) {
1543
            qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: invalid surface id %d\n",
1544
                              d->ram->update_surface);
1545
            break;
1546
        }
1547
        if (update.left >= update.right || update.top >= update.bottom ||
1548
            update.left < 0 || update.top < 0) {
1549
            qxl_set_guest_bug(d,
1550
                    "QXL_IO_UPDATE_AREA: invalid area (%ux%u)x(%ux%u)\n",
1551
                    update.left, update.top, update.right, update.bottom);
1552
            break;
1553
        }
1554
        if (async == QXL_ASYNC) {
1555
            cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
1556
                                    QXL_IO_UPDATE_AREA_ASYNC);
1557
            cookie->u.area = update;
1558
        }
1559
        qxl_spice_update_area(d, d->ram->update_surface,
1560
                              cookie ? &cookie->u.area : &update,
1561
                              NULL, 0, 0, async, cookie);
1562
        break;
1563
    }
1564
    case QXL_IO_NOTIFY_CMD:
1565
        qemu_spice_wakeup(&d->ssd);
1566
        break;
1567
    case QXL_IO_NOTIFY_CURSOR:
1568
        qemu_spice_wakeup(&d->ssd);
1569
        break;
1570
    case QXL_IO_UPDATE_IRQ:
1571
        qxl_update_irq(d);
1572
        break;
1573
    case QXL_IO_NOTIFY_OOM:
1574
        if (!SPICE_RING_IS_EMPTY(&d->ram->release_ring)) {
1575
            break;
1576
        }
1577
        d->oom_running = 1;
1578
        qxl_spice_oom(d);
1579
        d->oom_running = 0;
1580
        break;
1581
    case QXL_IO_SET_MODE:
1582
        qxl_set_mode(d, val, 0);
1583
        break;
1584
    case QXL_IO_LOG:
1585
        trace_qxl_io_log(d->id, d->ram->log_buf);
1586
        if (d->guestdebug) {
1587
            fprintf(stderr, "qxl/guest-%d: %" PRId64 ": %s", d->id,
1588
                    qemu_get_clock_ns(vm_clock), d->ram->log_buf);
1589
        }
1590
        break;
1591
    case QXL_IO_RESET:
1592
        qxl_hard_reset(d, 0);
1593
        break;
1594
    case QXL_IO_MEMSLOT_ADD:
1595
        if (val >= NUM_MEMSLOTS) {
1596
            qxl_set_guest_bug(d, "QXL_IO_MEMSLOT_ADD: val out of range");
1597
            break;
1598
        }
1599
        if (d->guest_slots[val].active) {
1600
            qxl_set_guest_bug(d,
1601
                        "QXL_IO_MEMSLOT_ADD: memory slot already active");
1602
            break;
1603
        }
1604
        d->guest_slots[val].slot = d->ram->mem_slot;
1605
        qxl_add_memslot(d, val, 0, async);
1606
        break;
1607
    case QXL_IO_MEMSLOT_DEL:
1608
        if (val >= NUM_MEMSLOTS) {
1609
            qxl_set_guest_bug(d, "QXL_IO_MEMSLOT_DEL: val out of range");
1610
            break;
1611
        }
1612
        qxl_del_memslot(d, val);
1613
        break;
1614
    case QXL_IO_CREATE_PRIMARY:
1615
        if (val != 0) {
1616
            qxl_set_guest_bug(d, "QXL_IO_CREATE_PRIMARY (async=%d): val != 0",
1617
                          async);
1618
            goto cancel_async;
1619
        }
1620
        d->guest_primary.surface = d->ram->create_surface;
1621
        qxl_create_guest_primary(d, 0, async);
1622
        break;
1623
    case QXL_IO_DESTROY_PRIMARY:
1624
        if (val != 0) {
1625
            qxl_set_guest_bug(d, "QXL_IO_DESTROY_PRIMARY (async=%d): val != 0",
1626
                          async);
1627
            goto cancel_async;
1628
        }
1629
        if (!qxl_destroy_primary(d, async)) {
1630
            trace_qxl_io_destroy_primary_ignored(d->id,
1631
                                                 qxl_mode_to_string(d->mode));
1632
            goto cancel_async;
1633
        }
1634
        break;
1635
    case QXL_IO_DESTROY_SURFACE_WAIT:
1636
        if (val >= d->ssd.num_surfaces) {
1637
            qxl_set_guest_bug(d, "QXL_IO_DESTROY_SURFACE (async=%d):"
1638
                             "%" PRIu64 " >= NUM_SURFACES", async, val);
1639
            goto cancel_async;
1640
        }
1641
        qxl_spice_destroy_surface_wait(d, val, async);
1642
        break;
1643
    case QXL_IO_FLUSH_RELEASE: {
1644
        QXLReleaseRing *ring = &d->ram->release_ring;
1645
        if (ring->prod - ring->cons + 1 == ring->num_items) {
1646
            fprintf(stderr,
1647
                "ERROR: no flush, full release ring [p%d,%dc]\n",
1648
                ring->prod, ring->cons);
1649
        }
1650
        qxl_push_free_res(d, 1 /* flush */);
1651
        break;
1652
    }
1653
    case QXL_IO_FLUSH_SURFACES_ASYNC:
1654
        qxl_spice_flush_surfaces_async(d);
1655
        break;
1656
    case QXL_IO_DESTROY_ALL_SURFACES:
1657
        d->mode = QXL_MODE_UNDEFINED;
1658
        qxl_spice_destroy_surfaces(d, async);
1659
        break;
1660
    case QXL_IO_MONITORS_CONFIG_ASYNC:
1661
        qxl_spice_monitors_config_async(d, 0);
1662
        break;
1663
    default:
1664
        qxl_set_guest_bug(d, "%s: unexpected ioport=0x%x\n", __func__, io_port);
1665
    }
1666
    return;
1667
cancel_async:
1668
    if (async) {
1669
        qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
1670
        qemu_mutex_lock(&d->async_lock);
1671
        d->current_async = QXL_UNDEFINED_IO;
1672
        qemu_mutex_unlock(&d->async_lock);
1673
    }
1674
}
1675

    
1676
static uint64_t ioport_read(void *opaque, hwaddr addr,
1677
                            unsigned size)
1678
{
1679
    PCIQXLDevice *qxl = opaque;
1680

    
1681
    trace_qxl_io_read_unexpected(qxl->id);
1682
    return 0xff;
1683
}
1684

    
1685
static const MemoryRegionOps qxl_io_ops = {
1686
    .read = ioport_read,
1687
    .write = ioport_write,
1688
    .valid = {
1689
        .min_access_size = 1,
1690
        .max_access_size = 1,
1691
    },
1692
};
1693

    
1694
static void pipe_read(void *opaque)
1695
{
1696
    PCIQXLDevice *d = opaque;
1697
    char dummy;
1698
    int len;
1699

    
1700
    do {
1701
        len = read(d->pipe[0], &dummy, sizeof(dummy));
1702
    } while (len == sizeof(dummy));
1703
    qxl_update_irq(d);
1704
}
1705

    
1706
static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
1707
{
1708
    uint32_t old_pending;
1709
    uint32_t le_events = cpu_to_le32(events);
1710

    
1711
    trace_qxl_send_events(d->id, events);
1712
    if (!qemu_spice_display_is_running(&d->ssd)) {
1713
        /* spice-server tracks guest running state and should not do this */
1714
        fprintf(stderr, "%s: spice-server bug: guest stopped, ignoring\n",
1715
                __func__);
1716
        trace_qxl_send_events_vm_stopped(d->id, events);
1717
        return;
1718
    }
1719
    old_pending = __sync_fetch_and_or(&d->ram->int_pending, le_events);
1720
    if ((old_pending & le_events) == le_events) {
1721
        return;
1722
    }
1723
    if (qemu_thread_is_self(&d->main)) {
1724
        qxl_update_irq(d);
1725
    } else {
1726
        if (write(d->pipe[1], d, 1) != 1) {
1727
            dprint(d, 1, "%s: write to pipe failed\n", __func__);
1728
        }
1729
    }
1730
}
1731

    
1732
static void init_pipe_signaling(PCIQXLDevice *d)
1733
{
1734
    if (pipe(d->pipe) < 0) {
1735
        fprintf(stderr, "%s:%s: qxl pipe creation failed\n",
1736
                __FILE__, __func__);
1737
        exit(1);
1738
    }
1739
    fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
1740
    fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
1741
    fcntl(d->pipe[0], F_SETOWN, getpid());
1742

    
1743
    qemu_thread_get_self(&d->main);
1744
    qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
1745
}
1746

    
1747
/* graphics console */
1748

    
1749
static void qxl_hw_update(void *opaque)
1750
{
1751
    PCIQXLDevice *qxl = opaque;
1752
    VGACommonState *vga = &qxl->vga;
1753

    
1754
    switch (qxl->mode) {
1755
    case QXL_MODE_VGA:
1756
        vga->update(vga);
1757
        break;
1758
    case QXL_MODE_COMPAT:
1759
    case QXL_MODE_NATIVE:
1760
        qxl_render_update(qxl);
1761
        break;
1762
    default:
1763
        break;
1764
    }
1765
}
1766

    
1767
static void qxl_hw_invalidate(void *opaque)
1768
{
1769
    PCIQXLDevice *qxl = opaque;
1770
    VGACommonState *vga = &qxl->vga;
1771

    
1772
    vga->invalidate(vga);
1773
}
1774

    
1775
static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch,
1776
                               Error **errp)
1777
{
1778
    PCIQXLDevice *qxl = opaque;
1779
    VGACommonState *vga = &qxl->vga;
1780

    
1781
    switch (qxl->mode) {
1782
    case QXL_MODE_COMPAT:
1783
    case QXL_MODE_NATIVE:
1784
        qxl_render_update(qxl);
1785
        ppm_save(filename, qxl->ssd.ds, errp);
1786
        break;
1787
    case QXL_MODE_VGA:
1788
        vga->screen_dump(vga, filename, cswitch, errp);
1789
        break;
1790
    default:
1791
        break;
1792
    }
1793
}
1794

    
1795
static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
1796
{
1797
    PCIQXLDevice *qxl = opaque;
1798
    VGACommonState *vga = &qxl->vga;
1799

    
1800
    if (qxl->mode == QXL_MODE_VGA) {
1801
        vga->text_update(vga, chardata);
1802
        return;
1803
    }
1804
}
1805

    
1806
static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
1807
{
1808
    uintptr_t vram_start;
1809
    int i;
1810

    
1811
    if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) {
1812
        return;
1813
    }
1814

    
1815
    /* dirty the primary surface */
1816
    qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
1817
                  qxl->shadow_rom.surface0_area_size);
1818

    
1819
    vram_start = (uintptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
1820

    
1821
    /* dirty the off-screen surfaces */
1822
    for (i = 0; i < qxl->ssd.num_surfaces; i++) {
1823
        QXLSurfaceCmd *cmd;
1824
        intptr_t surface_offset;
1825
        int surface_size;
1826

    
1827
        if (qxl->guest_surfaces.cmds[i] == 0) {
1828
            continue;
1829
        }
1830

    
1831
        cmd = qxl_phys2virt(qxl, qxl->guest_surfaces.cmds[i],
1832
                            MEMSLOT_GROUP_GUEST);
1833
        assert(cmd);
1834
        assert(cmd->type == QXL_SURFACE_CMD_CREATE);
1835
        surface_offset = (intptr_t)qxl_phys2virt(qxl,
1836
                                                 cmd->u.surface_create.data,
1837
                                                 MEMSLOT_GROUP_GUEST);
1838
        assert(surface_offset);
1839
        surface_offset -= vram_start;
1840
        surface_size = cmd->u.surface_create.height *
1841
                       abs(cmd->u.surface_create.stride);
1842
        trace_qxl_surfaces_dirty(qxl->id, i, (int)surface_offset, surface_size);
1843
        qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
1844
    }
1845
}
1846

    
1847
static void qxl_vm_change_state_handler(void *opaque, int running,
1848
                                        RunState state)
1849
{
1850
    PCIQXLDevice *qxl = opaque;
1851

    
1852
    if (running) {
1853
        /*
1854
         * if qxl_send_events was called from spice server context before
1855
         * migration ended, qxl_update_irq for these events might not have been
1856
         * called
1857
         */
1858
         qxl_update_irq(qxl);
1859
    } else {
1860
        /* make sure surfaces are saved before migration */
1861
        qxl_dirty_surfaces(qxl);
1862
    }
1863
}
1864

    
1865
/* display change listener */
1866

    
1867
static void display_update(DisplayChangeListener *dcl,
1868
                           int x, int y, int w, int h)
1869
{
1870
    PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
1871

    
1872
    if (qxl->mode == QXL_MODE_VGA) {
1873
        qemu_spice_display_update(&qxl->ssd, x, y, w, h);
1874
    }
1875
}
1876

    
1877
static void display_switch(DisplayChangeListener *dcl,
1878
                           struct DisplaySurface *surface)
1879
{
1880
    PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
1881

    
1882
    qxl->ssd.ds = surface;
1883
    if (qxl->mode == QXL_MODE_VGA) {
1884
        qemu_spice_display_switch(&qxl->ssd, surface);
1885
    }
1886
}
1887

    
1888
static void display_refresh(DisplayChangeListener *dcl)
1889
{
1890
    PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
1891

    
1892
    if (qxl->mode == QXL_MODE_VGA) {
1893
        qemu_spice_display_refresh(&qxl->ssd);
1894
    } else {
1895
        qemu_mutex_lock(&qxl->ssd.lock);
1896
        qemu_spice_cursor_refresh_unlocked(&qxl->ssd);
1897
        qemu_mutex_unlock(&qxl->ssd.lock);
1898
    }
1899
}
1900

    
1901
static DisplayChangeListenerOps display_listener_ops = {
1902
    .dpy_name        = "spice/qxl",
1903
    .dpy_gfx_update  = display_update,
1904
    .dpy_gfx_switch  = display_switch,
1905
    .dpy_refresh     = display_refresh,
1906
};
1907

    
1908
static void qxl_init_ramsize(PCIQXLDevice *qxl)
1909
{
1910
    /* vga mode framebuffer / primary surface (bar 0, first part) */
1911
    if (qxl->vgamem_size_mb < 8) {
1912
        qxl->vgamem_size_mb = 8;
1913
    }
1914
    qxl->vgamem_size = qxl->vgamem_size_mb * 1024 * 1024;
1915

    
1916
    /* vga ram (bar 0, total) */
1917
    if (qxl->ram_size_mb != -1) {
1918
        qxl->vga.vram_size = qxl->ram_size_mb * 1024 * 1024;
1919
    }
1920
    if (qxl->vga.vram_size < qxl->vgamem_size * 2) {
1921
        qxl->vga.vram_size = qxl->vgamem_size * 2;
1922
    }
1923

    
1924
    /* vram32 (surfaces, 32bit, bar 1) */
1925
    if (qxl->vram32_size_mb != -1) {
1926
        qxl->vram32_size = qxl->vram32_size_mb * 1024 * 1024;
1927
    }
1928
    if (qxl->vram32_size < 4096) {
1929
        qxl->vram32_size = 4096;
1930
    }
1931

    
1932
    /* vram (surfaces, 64bit, bar 4+5) */
1933
    if (qxl->vram_size_mb != -1) {
1934
        qxl->vram_size = qxl->vram_size_mb * 1024 * 1024;
1935
    }
1936
    if (qxl->vram_size < qxl->vram32_size) {
1937
        qxl->vram_size = qxl->vram32_size;
1938
    }
1939

    
1940
    if (qxl->revision == 1) {
1941
        qxl->vram32_size = 4096;
1942
        qxl->vram_size = 4096;
1943
    }
1944
    qxl->vgamem_size = msb_mask(qxl->vgamem_size * 2 - 1);
1945
    qxl->vga.vram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
1946
    qxl->vram32_size = msb_mask(qxl->vram32_size * 2 - 1);
1947
    qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
1948
}
1949

    
1950
static int qxl_init_common(PCIQXLDevice *qxl)
1951
{
1952
    uint8_t* config = qxl->pci.config;
1953
    uint32_t pci_device_rev;
1954
    uint32_t io_size;
1955

    
1956
    qxl->mode = QXL_MODE_UNDEFINED;
1957
    qxl->generation = 1;
1958
    qxl->num_memslots = NUM_MEMSLOTS;
1959
    qemu_mutex_init(&qxl->track_lock);
1960
    qemu_mutex_init(&qxl->async_lock);
1961
    qxl->current_async = QXL_UNDEFINED_IO;
1962
    qxl->guest_bug = 0;
1963

    
1964
    switch (qxl->revision) {
1965
    case 1: /* spice 0.4 -- qxl-1 */
1966
        pci_device_rev = QXL_REVISION_STABLE_V04;
1967
        io_size = 8;
1968
        break;
1969
    case 2: /* spice 0.6 -- qxl-2 */
1970
        pci_device_rev = QXL_REVISION_STABLE_V06;
1971
        io_size = 16;
1972
        break;
1973
    case 3: /* qxl-3 */
1974
        pci_device_rev = QXL_REVISION_STABLE_V10;
1975
        io_size = 32; /* PCI region size must be pow2 */
1976
        break;
1977
    case 4: /* qxl-4 */
1978
        pci_device_rev = QXL_REVISION_STABLE_V12;
1979
        io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
1980
        break;
1981
    default:
1982
        error_report("Invalid revision %d for qxl device (max %d)",
1983
                     qxl->revision, QXL_DEFAULT_REVISION);
1984
        return -1;
1985
    }
1986

    
1987
    pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
1988
    pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
1989

    
1990
    qxl->rom_size = qxl_rom_size();
1991
    memory_region_init_ram(&qxl->rom_bar, "qxl.vrom", qxl->rom_size);
1992
    vmstate_register_ram(&qxl->rom_bar, &qxl->pci.qdev);
1993
    init_qxl_rom(qxl);
1994
    init_qxl_ram(qxl);
1995

    
1996
    qxl->guest_surfaces.cmds = g_new0(QXLPHYSICAL, qxl->ssd.num_surfaces);
1997
    memory_region_init_ram(&qxl->vram_bar, "qxl.vram", qxl->vram_size);
1998
    vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev);
1999
    memory_region_init_alias(&qxl->vram32_bar, "qxl.vram32", &qxl->vram_bar,
2000
                             0, qxl->vram32_size);
2001

    
2002
    memory_region_init_io(&qxl->io_bar, &qxl_io_ops, qxl,
2003
                          "qxl-ioports", io_size);
2004
    if (qxl->id == 0) {
2005
        vga_dirty_log_start(&qxl->vga);
2006
    }
2007
    memory_region_set_flush_coalesced(&qxl->io_bar);
2008

    
2009

    
2010
    pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX,
2011
                     PCI_BASE_ADDRESS_SPACE_IO, &qxl->io_bar);
2012

    
2013
    pci_register_bar(&qxl->pci, QXL_ROM_RANGE_INDEX,
2014
                     PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->rom_bar);
2015

    
2016
    pci_register_bar(&qxl->pci, QXL_RAM_RANGE_INDEX,
2017
                     PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vga.vram);
2018

    
2019
    pci_register_bar(&qxl->pci, QXL_VRAM_RANGE_INDEX,
2020
                     PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vram32_bar);
2021

    
2022
    if (qxl->vram32_size < qxl->vram_size) {
2023
        /*
2024
         * Make the 64bit vram bar show up only in case it is
2025
         * configured to be larger than the 32bit vram bar.
2026
         */
2027
        pci_register_bar(&qxl->pci, QXL_VRAM64_RANGE_INDEX,
2028
                         PCI_BASE_ADDRESS_SPACE_MEMORY |
2029
                         PCI_BASE_ADDRESS_MEM_TYPE_64 |
2030
                         PCI_BASE_ADDRESS_MEM_PREFETCH,
2031
                         &qxl->vram_bar);
2032
    }
2033

    
2034
    /* print pci bar details */
2035
    dprint(qxl, 1, "ram/%s: %d MB [region 0]\n",
2036
           qxl->id == 0 ? "pri" : "sec",
2037
           qxl->vga.vram_size / (1024*1024));
2038
    dprint(qxl, 1, "vram/32: %d MB [region 1]\n",
2039
           qxl->vram32_size / (1024*1024));
2040
    dprint(qxl, 1, "vram/64: %d MB %s\n",
2041
           qxl->vram_size / (1024*1024),
2042
           qxl->vram32_size < qxl->vram_size ? "[region 4]" : "[unmapped]");
2043

    
2044
    qxl->ssd.qxl.base.sif = &qxl_interface.base;
2045
    qxl->ssd.qxl.id = qxl->id;
2046
    if (qemu_spice_add_interface(&qxl->ssd.qxl.base) != 0) {
2047
        error_report("qxl interface %d.%d not supported by spice-server",
2048
                     SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
2049
        return -1;
2050
    }
2051
    qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
2052

    
2053
    init_pipe_signaling(qxl);
2054
    qxl_reset_state(qxl);
2055

    
2056
    qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl);
2057

    
2058
    return 0;
2059
}
2060

    
2061
static int qxl_init_primary(PCIDevice *dev)
2062
{
2063
    PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
2064
    VGACommonState *vga = &qxl->vga;
2065
    PortioList *qxl_vga_port_list = g_new(PortioList, 1);
2066
    DisplayState *ds;
2067
    int rc;
2068

    
2069
    qxl->id = 0;
2070
    qxl_init_ramsize(qxl);
2071
    vga->vram_size_mb = qxl->vga.vram_size >> 20;
2072
    vga_common_init(vga);
2073
    vga_init(vga, pci_address_space(dev), pci_address_space_io(dev), false);
2074
    portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga");
2075
    portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
2076

    
2077
    vga->con = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
2078
                                    qxl_hw_screen_dump, qxl_hw_text_update,
2079
                                    qxl);
2080
    qxl->ssd.con = vga->con,
2081
    qemu_spice_display_init_common(&qxl->ssd);
2082

    
2083
    rc = qxl_init_common(qxl);
2084
    if (rc != 0) {
2085
        return rc;
2086
    }
2087

    
2088
    qxl->ssd.dcl.ops = &display_listener_ops;
2089
    ds = qemu_console_displaystate(vga->con);
2090
    register_displaychangelistener(ds, &qxl->ssd.dcl);
2091
    return rc;
2092
}
2093

    
2094
static int qxl_init_secondary(PCIDevice *dev)
2095
{
2096
    static int device_id = 1;
2097
    PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
2098

    
2099
    qxl->id = device_id++;
2100
    qxl_init_ramsize(qxl);
2101
    memory_region_init_ram(&qxl->vga.vram, "qxl.vgavram", qxl->vga.vram_size);
2102
    vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev);
2103
    qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
2104

    
2105
    return qxl_init_common(qxl);
2106
}
2107

    
2108
static void qxl_pre_save(void *opaque)
2109
{
2110
    PCIQXLDevice* d = opaque;
2111
    uint8_t *ram_start = d->vga.vram_ptr;
2112

    
2113
    trace_qxl_pre_save(d->id);
2114
    if (d->last_release == NULL) {
2115
        d->last_release_offset = 0;
2116
    } else {
2117
        d->last_release_offset = (uint8_t *)d->last_release - ram_start;
2118
    }
2119
    assert(d->last_release_offset < d->vga.vram_size);
2120
}
2121

    
2122
static int qxl_pre_load(void *opaque)
2123
{
2124
    PCIQXLDevice* d = opaque;
2125

    
2126
    trace_qxl_pre_load(d->id);
2127
    qxl_hard_reset(d, 1);
2128
    qxl_exit_vga_mode(d);
2129
    return 0;
2130
}
2131

    
2132
static void qxl_create_memslots(PCIQXLDevice *d)
2133
{
2134
    int i;
2135

    
2136
    for (i = 0; i < NUM_MEMSLOTS; i++) {
2137
        if (!d->guest_slots[i].active) {
2138
            continue;
2139
        }
2140
        qxl_add_memslot(d, i, 0, QXL_SYNC);
2141
    }
2142
}
2143

    
2144
static int qxl_post_load(void *opaque, int version)
2145
{
2146
    PCIQXLDevice* d = opaque;
2147
    uint8_t *ram_start = d->vga.vram_ptr;
2148
    QXLCommandExt *cmds;
2149
    int in, out, newmode;
2150

    
2151
    assert(d->last_release_offset < d->vga.vram_size);
2152
    if (d->last_release_offset == 0) {
2153
        d->last_release = NULL;
2154
    } else {
2155
        d->last_release = (QXLReleaseInfo *)(ram_start + d->last_release_offset);
2156
    }
2157

    
2158
    d->modes = (QXLModes*)((uint8_t*)d->rom + d->rom->modes_offset);
2159

    
2160
    trace_qxl_post_load(d->id, qxl_mode_to_string(d->mode));
2161
    newmode = d->mode;
2162
    d->mode = QXL_MODE_UNDEFINED;
2163

    
2164
    switch (newmode) {
2165
    case QXL_MODE_UNDEFINED:
2166
        qxl_create_memslots(d);
2167
        break;
2168
    case QXL_MODE_VGA:
2169
        qxl_create_memslots(d);
2170
        qxl_enter_vga_mode(d);
2171
        break;
2172
    case QXL_MODE_NATIVE:
2173
        qxl_create_memslots(d);
2174
        qxl_create_guest_primary(d, 1, QXL_SYNC);
2175

    
2176
        /* replay surface-create and cursor-set commands */
2177
        cmds = g_malloc0(sizeof(QXLCommandExt) * (d->ssd.num_surfaces + 1));
2178
        for (in = 0, out = 0; in < d->ssd.num_surfaces; in++) {
2179
            if (d->guest_surfaces.cmds[in] == 0) {
2180
                continue;
2181
            }
2182
            cmds[out].cmd.data = d->guest_surfaces.cmds[in];
2183
            cmds[out].cmd.type = QXL_CMD_SURFACE;
2184
            cmds[out].group_id = MEMSLOT_GROUP_GUEST;
2185
            out++;
2186
        }
2187
        if (d->guest_cursor) {
2188
            cmds[out].cmd.data = d->guest_cursor;
2189
            cmds[out].cmd.type = QXL_CMD_CURSOR;
2190
            cmds[out].group_id = MEMSLOT_GROUP_GUEST;
2191
            out++;
2192
        }
2193
        qxl_spice_loadvm_commands(d, cmds, out);
2194
        g_free(cmds);
2195
        if (d->guest_monitors_config) {
2196
            qxl_spice_monitors_config_async(d, 1);
2197
        }
2198
        break;
2199
    case QXL_MODE_COMPAT:
2200
        /* note: no need to call qxl_create_memslots, qxl_set_mode
2201
         * creates the mem slot. */
2202
        qxl_set_mode(d, d->shadow_rom.mode, 1);
2203
        break;
2204
    }
2205
    return 0;
2206
}
2207

    
2208
#define QXL_SAVE_VERSION 21
2209

    
2210
static bool qxl_monitors_config_needed(void *opaque)
2211
{
2212
    PCIQXLDevice *qxl = opaque;
2213

    
2214
    return qxl->guest_monitors_config != 0;
2215
}
2216

    
2217

    
2218
static VMStateDescription qxl_memslot = {
2219
    .name               = "qxl-memslot",
2220
    .version_id         = QXL_SAVE_VERSION,
2221
    .minimum_version_id = QXL_SAVE_VERSION,
2222
    .fields = (VMStateField[]) {
2223
        VMSTATE_UINT64(slot.mem_start, struct guest_slots),
2224
        VMSTATE_UINT64(slot.mem_end,   struct guest_slots),
2225
        VMSTATE_UINT32(active,         struct guest_slots),
2226
        VMSTATE_END_OF_LIST()
2227
    }
2228
};
2229

    
2230
static VMStateDescription qxl_surface = {
2231
    .name               = "qxl-surface",
2232
    .version_id         = QXL_SAVE_VERSION,
2233
    .minimum_version_id = QXL_SAVE_VERSION,
2234
    .fields = (VMStateField[]) {
2235
        VMSTATE_UINT32(width,      QXLSurfaceCreate),
2236
        VMSTATE_UINT32(height,     QXLSurfaceCreate),
2237
        VMSTATE_INT32(stride,      QXLSurfaceCreate),
2238
        VMSTATE_UINT32(format,     QXLSurfaceCreate),
2239
        VMSTATE_UINT32(position,   QXLSurfaceCreate),
2240
        VMSTATE_UINT32(mouse_mode, QXLSurfaceCreate),
2241
        VMSTATE_UINT32(flags,      QXLSurfaceCreate),
2242
        VMSTATE_UINT32(type,       QXLSurfaceCreate),
2243
        VMSTATE_UINT64(mem,        QXLSurfaceCreate),
2244
        VMSTATE_END_OF_LIST()
2245
    }
2246
};
2247

    
2248
static VMStateDescription qxl_vmstate_monitors_config = {
2249
    .name               = "qxl/monitors-config",
2250
    .version_id         = 1,
2251
    .minimum_version_id = 1,
2252
    .fields = (VMStateField[]) {
2253
        VMSTATE_UINT64(guest_monitors_config, PCIQXLDevice),
2254
        VMSTATE_END_OF_LIST()
2255
    },
2256
};
2257

    
2258
static VMStateDescription qxl_vmstate = {
2259
    .name               = "qxl",
2260
    .version_id         = QXL_SAVE_VERSION,
2261
    .minimum_version_id = QXL_SAVE_VERSION,
2262
    .pre_save           = qxl_pre_save,
2263
    .pre_load           = qxl_pre_load,
2264
    .post_load          = qxl_post_load,
2265
    .fields = (VMStateField[]) {
2266
        VMSTATE_PCI_DEVICE(pci, PCIQXLDevice),
2267
        VMSTATE_STRUCT(vga, PCIQXLDevice, 0, vmstate_vga_common, VGACommonState),
2268
        VMSTATE_UINT32(shadow_rom.mode, PCIQXLDevice),
2269
        VMSTATE_UINT32(num_free_res, PCIQXLDevice),
2270
        VMSTATE_UINT32(last_release_offset, PCIQXLDevice),
2271
        VMSTATE_UINT32(mode, PCIQXLDevice),
2272
        VMSTATE_UINT32(ssd.unique, PCIQXLDevice),
2273
        VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice),
2274
        VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0,
2275
                             qxl_memslot, struct guest_slots),
2276
        VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0,
2277
                       qxl_surface, QXLSurfaceCreate),
2278
        VMSTATE_INT32_EQUAL(ssd.num_surfaces, PCIQXLDevice),
2279
        VMSTATE_VARRAY_INT32(guest_surfaces.cmds, PCIQXLDevice,
2280
                             ssd.num_surfaces, 0,
2281
                             vmstate_info_uint64, uint64_t),
2282
        VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
2283
        VMSTATE_END_OF_LIST()
2284
    },
2285
    .subsections = (VMStateSubsection[]) {
2286
        {
2287
            .vmsd = &qxl_vmstate_monitors_config,
2288
            .needed = qxl_monitors_config_needed,
2289
        }, {
2290
            /* empty */
2291
        }
2292
    }
2293
};
2294

    
2295
static Property qxl_properties[] = {
2296
        DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
2297
                           64 * 1024 * 1024),
2298
        DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram32_size,
2299
                           64 * 1024 * 1024),
2300
        DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
2301
                           QXL_DEFAULT_REVISION),
2302
        DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
2303
        DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
2304
        DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
2305
        DEFINE_PROP_UINT32("ram_size_mb",  PCIQXLDevice, ram_size_mb, -1),
2306
        DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram32_size_mb, -1),
2307
        DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1),
2308
        DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 16),
2309
        DEFINE_PROP_INT32("surfaces", PCIQXLDevice, ssd.num_surfaces, 1024),
2310
        DEFINE_PROP_END_OF_LIST(),
2311
};
2312

    
2313
static void qxl_primary_class_init(ObjectClass *klass, void *data)
2314
{
2315
    DeviceClass *dc = DEVICE_CLASS(klass);
2316
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
2317

    
2318
    k->no_hotplug = 1;
2319
    k->init = qxl_init_primary;
2320
    k->romfile = "vgabios-qxl.bin";
2321
    k->vendor_id = REDHAT_PCI_VENDOR_ID;
2322
    k->device_id = QXL_DEVICE_ID_STABLE;
2323
    k->class_id = PCI_CLASS_DISPLAY_VGA;
2324
    dc->desc = "Spice QXL GPU (primary, vga compatible)";
2325
    dc->reset = qxl_reset_handler;
2326
    dc->vmsd = &qxl_vmstate;
2327
    dc->props = qxl_properties;
2328
}
2329

    
2330
static const TypeInfo qxl_primary_info = {
2331
    .name          = "qxl-vga",
2332
    .parent        = TYPE_PCI_DEVICE,
2333
    .instance_size = sizeof(PCIQXLDevice),
2334
    .class_init    = qxl_primary_class_init,
2335
};
2336

    
2337
static void qxl_secondary_class_init(ObjectClass *klass, void *data)
2338
{
2339
    DeviceClass *dc = DEVICE_CLASS(klass);
2340
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
2341

    
2342
    k->init = qxl_init_secondary;
2343
    k->vendor_id = REDHAT_PCI_VENDOR_ID;
2344
    k->device_id = QXL_DEVICE_ID_STABLE;
2345
    k->class_id = PCI_CLASS_DISPLAY_OTHER;
2346
    dc->desc = "Spice QXL GPU (secondary)";
2347
    dc->reset = qxl_reset_handler;
2348
    dc->vmsd = &qxl_vmstate;
2349
    dc->props = qxl_properties;
2350
}
2351

    
2352
static const TypeInfo qxl_secondary_info = {
2353
    .name          = "qxl",
2354
    .parent        = TYPE_PCI_DEVICE,
2355
    .instance_size = sizeof(PCIQXLDevice),
2356
    .class_init    = qxl_secondary_class_init,
2357
};
2358

    
2359
static void qxl_register_types(void)
2360
{
2361
    type_register_static(&qxl_primary_info);
2362
    type_register_static(&qxl_secondary_info);
2363
}
2364

    
2365
type_init(qxl_register_types)