cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

virtio-gpu.c (47451B)


      1/*
      2 * Virtio GPU Device
      3 *
      4 * Copyright Red Hat, Inc. 2013-2014
      5 *
      6 * Authors:
      7 *     Dave Airlie <airlied@redhat.com>
      8 *     Gerd Hoffmann <kraxel@redhat.com>
      9 *
     10 * This work is licensed under the terms of the GNU GPL, version 2 or later.
     11 * See the COPYING file in the top-level directory.
     12 */
     13
     14#include "qemu/osdep.h"
     15#include "qemu/units.h"
     16#include "qemu/iov.h"
     17#include "ui/console.h"
     18#include "trace.h"
     19#include "sysemu/dma.h"
     20#include "sysemu/sysemu.h"
     21#include "hw/virtio/virtio.h"
     22#include "migration/qemu-file-types.h"
     23#include "hw/virtio/virtio-gpu.h"
     24#include "hw/virtio/virtio-gpu-bswap.h"
     25#include "hw/virtio/virtio-gpu-pixman.h"
     26#include "hw/virtio/virtio-bus.h"
     27#include "hw/display/edid.h"
     28#include "hw/qdev-properties.h"
     29#include "qemu/log.h"
     30#include "qemu/module.h"
     31#include "qapi/error.h"
     32#include "qemu/error-report.h"
     33
     34#define VIRTIO_GPU_VM_VERSION 1
     35
     36static struct virtio_gpu_simple_resource*
     37virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
     38static struct virtio_gpu_simple_resource *
     39virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
     40                               bool require_backing,
     41                               const char *caller, uint32_t *error);
     42
     43static void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
     44                                       struct virtio_gpu_simple_resource *res);
     45
     46void virtio_gpu_update_cursor_data(VirtIOGPU *g,
     47                                   struct virtio_gpu_scanout *s,
     48                                   uint32_t resource_id)
     49{
     50    struct virtio_gpu_simple_resource *res;
     51    uint32_t pixels;
     52    void *data;
     53
     54    res = virtio_gpu_find_check_resource(g, resource_id, false,
     55                                         __func__, NULL);
     56    if (!res) {
     57        return;
     58    }
     59
     60    if (res->blob_size) {
     61        if (res->blob_size < (s->current_cursor->width *
     62                              s->current_cursor->height * 4)) {
     63            return;
     64        }
     65        data = res->blob;
     66    } else {
     67        if (pixman_image_get_width(res->image)  != s->current_cursor->width ||
     68            pixman_image_get_height(res->image) != s->current_cursor->height) {
     69            return;
     70        }
     71        data = pixman_image_get_data(res->image);
     72    }
     73
     74    pixels = s->current_cursor->width * s->current_cursor->height;
     75    memcpy(s->current_cursor->data, data,
     76           pixels * sizeof(uint32_t));
     77}
     78
     79static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
     80{
     81    struct virtio_gpu_scanout *s;
     82    VirtIOGPUClass *vgc = VIRTIO_GPU_GET_CLASS(g);
     83    bool move = cursor->hdr.type == VIRTIO_GPU_CMD_MOVE_CURSOR;
     84
     85    if (cursor->pos.scanout_id >= g->parent_obj.conf.max_outputs) {
     86        return;
     87    }
     88    s = &g->parent_obj.scanout[cursor->pos.scanout_id];
     89
     90    trace_virtio_gpu_update_cursor(cursor->pos.scanout_id,
     91                                   cursor->pos.x,
     92                                   cursor->pos.y,
     93                                   move ? "move" : "update",
     94                                   cursor->resource_id);
     95
     96    if (!move) {
     97        if (!s->current_cursor) {
     98            s->current_cursor = cursor_alloc(64, 64);
     99        }
    100
    101        s->current_cursor->hot_x = cursor->hot_x;
    102        s->current_cursor->hot_y = cursor->hot_y;
    103
    104        if (cursor->resource_id > 0) {
    105            vgc->update_cursor_data(g, s, cursor->resource_id);
    106        }
    107        dpy_cursor_define(s->con, s->current_cursor);
    108
    109        s->cursor = *cursor;
    110    } else {
    111        s->cursor.pos.x = cursor->pos.x;
    112        s->cursor.pos.y = cursor->pos.y;
    113    }
    114    dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y,
    115                  cursor->resource_id ? 1 : 0);
    116}
    117
    118static struct virtio_gpu_simple_resource *
    119virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id)
    120{
    121    struct virtio_gpu_simple_resource *res;
    122
    123    QTAILQ_FOREACH(res, &g->reslist, next) {
    124        if (res->resource_id == resource_id) {
    125            return res;
    126        }
    127    }
    128    return NULL;
    129}
    130
    131static struct virtio_gpu_simple_resource *
    132virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
    133                               bool require_backing,
    134                               const char *caller, uint32_t *error)
    135{
    136    struct virtio_gpu_simple_resource *res;
    137
    138    res = virtio_gpu_find_resource(g, resource_id);
    139    if (!res) {
    140        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid resource specified %d\n",
    141                      caller, resource_id);
    142        if (error) {
    143            *error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
    144        }
    145        return NULL;
    146    }
    147
    148    if (require_backing) {
    149        if (!res->iov || (!res->image && !res->blob)) {
    150            qemu_log_mask(LOG_GUEST_ERROR, "%s: no backing storage %d\n",
    151                          caller, resource_id);
    152            if (error) {
    153                *error = VIRTIO_GPU_RESP_ERR_UNSPEC;
    154            }
    155            return NULL;
    156        }
    157    }
    158
    159    return res;
    160}
    161
    162void virtio_gpu_ctrl_response(VirtIOGPU *g,
    163                              struct virtio_gpu_ctrl_command *cmd,
    164                              struct virtio_gpu_ctrl_hdr *resp,
    165                              size_t resp_len)
    166{
    167    size_t s;
    168
    169    if (cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE) {
    170        resp->flags |= VIRTIO_GPU_FLAG_FENCE;
    171        resp->fence_id = cmd->cmd_hdr.fence_id;
    172        resp->ctx_id = cmd->cmd_hdr.ctx_id;
    173    }
    174    virtio_gpu_ctrl_hdr_bswap(resp);
    175    s = iov_from_buf(cmd->elem.in_sg, cmd->elem.in_num, 0, resp, resp_len);
    176    if (s != resp_len) {
    177        qemu_log_mask(LOG_GUEST_ERROR,
    178                      "%s: response size incorrect %zu vs %zu\n",
    179                      __func__, s, resp_len);
    180    }
    181    virtqueue_push(cmd->vq, &cmd->elem, s);
    182    virtio_notify(VIRTIO_DEVICE(g), cmd->vq);
    183    cmd->finished = true;
    184}
    185
    186void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g,
    187                                     struct virtio_gpu_ctrl_command *cmd,
    188                                     enum virtio_gpu_ctrl_type type)
    189{
    190    struct virtio_gpu_ctrl_hdr resp;
    191
    192    memset(&resp, 0, sizeof(resp));
    193    resp.type = type;
    194    virtio_gpu_ctrl_response(g, cmd, &resp, sizeof(resp));
    195}
    196
    197void virtio_gpu_get_display_info(VirtIOGPU *g,
    198                                 struct virtio_gpu_ctrl_command *cmd)
    199{
    200    struct virtio_gpu_resp_display_info display_info;
    201
    202    trace_virtio_gpu_cmd_get_display_info();
    203    memset(&display_info, 0, sizeof(display_info));
    204    display_info.hdr.type = VIRTIO_GPU_RESP_OK_DISPLAY_INFO;
    205    virtio_gpu_base_fill_display_info(VIRTIO_GPU_BASE(g), &display_info);
    206    virtio_gpu_ctrl_response(g, cmd, &display_info.hdr,
    207                             sizeof(display_info));
    208}
    209
    210static void
    211virtio_gpu_generate_edid(VirtIOGPU *g, int scanout,
    212                         struct virtio_gpu_resp_edid *edid)
    213{
    214    VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
    215    qemu_edid_info info = {
    216        .width_mm = b->req_state[scanout].width_mm,
    217        .height_mm = b->req_state[scanout].height_mm,
    218        .prefx = b->req_state[scanout].width,
    219        .prefy = b->req_state[scanout].height,
    220    };
    221
    222    edid->size = cpu_to_le32(sizeof(edid->edid));
    223    qemu_edid_generate(edid->edid, sizeof(edid->edid), &info);
    224}
    225
    226void virtio_gpu_get_edid(VirtIOGPU *g,
    227                         struct virtio_gpu_ctrl_command *cmd)
    228{
    229    struct virtio_gpu_resp_edid edid;
    230    struct virtio_gpu_cmd_get_edid get_edid;
    231    VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
    232
    233    VIRTIO_GPU_FILL_CMD(get_edid);
    234    virtio_gpu_bswap_32(&get_edid, sizeof(get_edid));
    235
    236    if (get_edid.scanout >= b->conf.max_outputs) {
    237        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
    238        return;
    239    }
    240
    241    trace_virtio_gpu_cmd_get_edid(get_edid.scanout);
    242    memset(&edid, 0, sizeof(edid));
    243    edid.hdr.type = VIRTIO_GPU_RESP_OK_EDID;
    244    virtio_gpu_generate_edid(g, get_edid.scanout, &edid);
    245    virtio_gpu_ctrl_response(g, cmd, &edid.hdr, sizeof(edid));
    246}
    247
    248static uint32_t calc_image_hostmem(pixman_format_code_t pformat,
    249                                   uint32_t width, uint32_t height)
    250{
    251    /* Copied from pixman/pixman-bits-image.c, skip integer overflow check.
    252     * pixman_image_create_bits will fail in case it overflow.
    253     */
    254
    255    int bpp = PIXMAN_FORMAT_BPP(pformat);
    256    int stride = ((width * bpp + 0x1f) >> 5) * sizeof(uint32_t);
    257    return height * stride;
    258}
    259
    260static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
    261                                          struct virtio_gpu_ctrl_command *cmd)
    262{
    263    pixman_format_code_t pformat;
    264    struct virtio_gpu_simple_resource *res;
    265    struct virtio_gpu_resource_create_2d c2d;
    266
    267    VIRTIO_GPU_FILL_CMD(c2d);
    268    virtio_gpu_bswap_32(&c2d, sizeof(c2d));
    269    trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
    270                                       c2d.width, c2d.height);
    271
    272    if (c2d.resource_id == 0) {
    273        qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
    274                      __func__);
    275        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
    276        return;
    277    }
    278
    279    res = virtio_gpu_find_resource(g, c2d.resource_id);
    280    if (res) {
    281        qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
    282                      __func__, c2d.resource_id);
    283        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
    284        return;
    285    }
    286
    287    res = g_new0(struct virtio_gpu_simple_resource, 1);
    288
    289    res->width = c2d.width;
    290    res->height = c2d.height;
    291    res->format = c2d.format;
    292    res->resource_id = c2d.resource_id;
    293
    294    pformat = virtio_gpu_get_pixman_format(c2d.format);
    295    if (!pformat) {
    296        qemu_log_mask(LOG_GUEST_ERROR,
    297                      "%s: host couldn't handle guest format %d\n",
    298                      __func__, c2d.format);
    299        g_free(res);
    300        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
    301        return;
    302    }
    303
    304    res->hostmem = calc_image_hostmem(pformat, c2d.width, c2d.height);
    305    if (res->hostmem + g->hostmem < g->conf_max_hostmem) {
    306        res->image = pixman_image_create_bits(pformat,
    307                                              c2d.width,
    308                                              c2d.height,
    309                                              NULL, 0);
    310    }
    311
    312    if (!res->image) {
    313        qemu_log_mask(LOG_GUEST_ERROR,
    314                      "%s: resource creation failed %d %d %d\n",
    315                      __func__, c2d.resource_id, c2d.width, c2d.height);
    316        g_free(res);
    317        cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
    318        return;
    319    }
    320
    321    QTAILQ_INSERT_HEAD(&g->reslist, res, next);
    322    g->hostmem += res->hostmem;
    323}
    324
    325static void virtio_gpu_resource_create_blob(VirtIOGPU *g,
    326                                            struct virtio_gpu_ctrl_command *cmd)
    327{
    328    struct virtio_gpu_simple_resource *res;
    329    struct virtio_gpu_resource_create_blob cblob;
    330    int ret;
    331
    332    VIRTIO_GPU_FILL_CMD(cblob);
    333    virtio_gpu_create_blob_bswap(&cblob);
    334    trace_virtio_gpu_cmd_res_create_blob(cblob.resource_id, cblob.size);
    335
    336    if (cblob.resource_id == 0) {
    337        qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
    338                      __func__);
    339        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
    340        return;
    341    }
    342
    343    if (cblob.blob_mem != VIRTIO_GPU_BLOB_MEM_GUEST &&
    344        cblob.blob_flags != VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE) {
    345        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid memory type\n",
    346                      __func__);
    347        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
    348        return;
    349    }
    350
    351    if (virtio_gpu_find_resource(g, cblob.resource_id)) {
    352        qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
    353                      __func__, cblob.resource_id);
    354        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
    355        return;
    356    }
    357
    358    res = g_new0(struct virtio_gpu_simple_resource, 1);
    359    res->resource_id = cblob.resource_id;
    360    res->blob_size = cblob.size;
    361
    362    ret = virtio_gpu_create_mapping_iov(g, cblob.nr_entries, sizeof(cblob),
    363                                        cmd, &res->addrs, &res->iov,
    364                                        &res->iov_cnt);
    365    if (ret != 0) {
    366        cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
    367        g_free(res);
    368        return;
    369    }
    370
    371    virtio_gpu_init_udmabuf(res);
    372    QTAILQ_INSERT_HEAD(&g->reslist, res, next);
    373}
    374
    375static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id)
    376{
    377    struct virtio_gpu_scanout *scanout = &g->parent_obj.scanout[scanout_id];
    378    struct virtio_gpu_simple_resource *res;
    379
    380    if (scanout->resource_id == 0) {
    381        return;
    382    }
    383
    384    res = virtio_gpu_find_resource(g, scanout->resource_id);
    385    if (res) {
    386        res->scanout_bitmask &= ~(1 << scanout_id);
    387    }
    388
    389    dpy_gfx_replace_surface(scanout->con, NULL);
    390    scanout->resource_id = 0;
    391    scanout->ds = NULL;
    392    scanout->width = 0;
    393    scanout->height = 0;
    394}
    395
    396static void virtio_gpu_resource_destroy(VirtIOGPU *g,
    397                                        struct virtio_gpu_simple_resource *res)
    398{
    399    int i;
    400
    401    if (res->scanout_bitmask) {
    402        for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
    403            if (res->scanout_bitmask & (1 << i)) {
    404                virtio_gpu_disable_scanout(g, i);
    405            }
    406        }
    407    }
    408
    409    qemu_pixman_image_unref(res->image);
    410    virtio_gpu_cleanup_mapping(g, res);
    411    QTAILQ_REMOVE(&g->reslist, res, next);
    412    g->hostmem -= res->hostmem;
    413    g_free(res);
    414}
    415
    416static void virtio_gpu_resource_unref(VirtIOGPU *g,
    417                                      struct virtio_gpu_ctrl_command *cmd)
    418{
    419    struct virtio_gpu_simple_resource *res;
    420    struct virtio_gpu_resource_unref unref;
    421
    422    VIRTIO_GPU_FILL_CMD(unref);
    423    virtio_gpu_bswap_32(&unref, sizeof(unref));
    424    trace_virtio_gpu_cmd_res_unref(unref.resource_id);
    425
    426    res = virtio_gpu_find_resource(g, unref.resource_id);
    427    if (!res) {
    428        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
    429                      __func__, unref.resource_id);
    430        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
    431        return;
    432    }
    433    virtio_gpu_resource_destroy(g, res);
    434}
    435
    436static void virtio_gpu_transfer_to_host_2d(VirtIOGPU *g,
    437                                           struct virtio_gpu_ctrl_command *cmd)
    438{
    439    struct virtio_gpu_simple_resource *res;
    440    int h;
    441    uint32_t src_offset, dst_offset, stride;
    442    int bpp;
    443    pixman_format_code_t format;
    444    struct virtio_gpu_transfer_to_host_2d t2d;
    445
    446    VIRTIO_GPU_FILL_CMD(t2d);
    447    virtio_gpu_t2d_bswap(&t2d);
    448    trace_virtio_gpu_cmd_res_xfer_toh_2d(t2d.resource_id);
    449
    450    res = virtio_gpu_find_check_resource(g, t2d.resource_id, true,
    451                                         __func__, &cmd->error);
    452    if (!res || res->blob) {
    453        return;
    454    }
    455
    456    if (t2d.r.x > res->width ||
    457        t2d.r.y > res->height ||
    458        t2d.r.width > res->width ||
    459        t2d.r.height > res->height ||
    460        t2d.r.x + t2d.r.width > res->width ||
    461        t2d.r.y + t2d.r.height > res->height) {
    462        qemu_log_mask(LOG_GUEST_ERROR, "%s: transfer bounds outside resource"
    463                      " bounds for resource %d: %d %d %d %d vs %d %d\n",
    464                      __func__, t2d.resource_id, t2d.r.x, t2d.r.y,
    465                      t2d.r.width, t2d.r.height, res->width, res->height);
    466        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
    467        return;
    468    }
    469
    470    format = pixman_image_get_format(res->image);
    471    bpp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8);
    472    stride = pixman_image_get_stride(res->image);
    473
    474    if (t2d.offset || t2d.r.x || t2d.r.y ||
    475        t2d.r.width != pixman_image_get_width(res->image)) {
    476        void *img_data = pixman_image_get_data(res->image);
    477        for (h = 0; h < t2d.r.height; h++) {
    478            src_offset = t2d.offset + stride * h;
    479            dst_offset = (t2d.r.y + h) * stride + (t2d.r.x * bpp);
    480
    481            iov_to_buf(res->iov, res->iov_cnt, src_offset,
    482                       (uint8_t *)img_data
    483                       + dst_offset, t2d.r.width * bpp);
    484        }
    485    } else {
    486        iov_to_buf(res->iov, res->iov_cnt, 0,
    487                   pixman_image_get_data(res->image),
    488                   pixman_image_get_stride(res->image)
    489                   * pixman_image_get_height(res->image));
    490    }
    491}
    492
    493static void virtio_gpu_resource_flush(VirtIOGPU *g,
    494                                      struct virtio_gpu_ctrl_command *cmd)
    495{
    496    struct virtio_gpu_simple_resource *res;
    497    struct virtio_gpu_resource_flush rf;
    498    struct virtio_gpu_scanout *scanout;
    499    pixman_region16_t flush_region;
    500    int i;
    501
    502    VIRTIO_GPU_FILL_CMD(rf);
    503    virtio_gpu_bswap_32(&rf, sizeof(rf));
    504    trace_virtio_gpu_cmd_res_flush(rf.resource_id,
    505                                   rf.r.width, rf.r.height, rf.r.x, rf.r.y);
    506
    507    res = virtio_gpu_find_check_resource(g, rf.resource_id, false,
    508                                         __func__, &cmd->error);
    509    if (!res) {
    510        return;
    511    }
    512
    513    if (res->blob) {
    514        for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
    515            scanout = &g->parent_obj.scanout[i];
    516            if (scanout->resource_id == res->resource_id &&
    517                console_has_gl(scanout->con)) {
    518                dpy_gl_update(scanout->con, 0, 0, scanout->width,
    519                              scanout->height);
    520                return;
    521            }
    522        }
    523    }
    524
    525    if (!res->blob &&
    526        (rf.r.x > res->width ||
    527        rf.r.y > res->height ||
    528        rf.r.width > res->width ||
    529        rf.r.height > res->height ||
    530        rf.r.x + rf.r.width > res->width ||
    531        rf.r.y + rf.r.height > res->height)) {
    532        qemu_log_mask(LOG_GUEST_ERROR, "%s: flush bounds outside resource"
    533                      " bounds for resource %d: %d %d %d %d vs %d %d\n",
    534                      __func__, rf.resource_id, rf.r.x, rf.r.y,
    535                      rf.r.width, rf.r.height, res->width, res->height);
    536        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
    537        return;
    538    }
    539
    540    pixman_region_init_rect(&flush_region,
    541                            rf.r.x, rf.r.y, rf.r.width, rf.r.height);
    542    for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
    543        pixman_region16_t region, finalregion;
    544        pixman_box16_t *extents;
    545
    546        if (!(res->scanout_bitmask & (1 << i))) {
    547            continue;
    548        }
    549        scanout = &g->parent_obj.scanout[i];
    550
    551        pixman_region_init(&finalregion);
    552        pixman_region_init_rect(&region, scanout->x, scanout->y,
    553                                scanout->width, scanout->height);
    554
    555        pixman_region_intersect(&finalregion, &flush_region, &region);
    556        pixman_region_translate(&finalregion, -scanout->x, -scanout->y);
    557        extents = pixman_region_extents(&finalregion);
    558        /* work out the area we need to update for each console */
    559        dpy_gfx_update(g->parent_obj.scanout[i].con,
    560                       extents->x1, extents->y1,
    561                       extents->x2 - extents->x1,
    562                       extents->y2 - extents->y1);
    563
    564        pixman_region_fini(&region);
    565        pixman_region_fini(&finalregion);
    566    }
    567    pixman_region_fini(&flush_region);
    568}
    569
    570static void virtio_unref_resource(pixman_image_t *image, void *data)
    571{
    572    pixman_image_unref(data);
    573}
    574
    575static void virtio_gpu_update_scanout(VirtIOGPU *g,
    576                                      uint32_t scanout_id,
    577                                      struct virtio_gpu_simple_resource *res,
    578                                      struct virtio_gpu_rect *r)
    579{
    580    struct virtio_gpu_simple_resource *ores;
    581    struct virtio_gpu_scanout *scanout;
    582
    583    scanout = &g->parent_obj.scanout[scanout_id];
    584    ores = virtio_gpu_find_resource(g, scanout->resource_id);
    585    if (ores) {
    586        ores->scanout_bitmask &= ~(1 << scanout_id);
    587    }
    588
    589    res->scanout_bitmask |= (1 << scanout_id);
    590    scanout->resource_id = res->resource_id;
    591    scanout->x = r->x;
    592    scanout->y = r->y;
    593    scanout->width = r->width;
    594    scanout->height = r->height;
    595}
    596
    597static void virtio_gpu_do_set_scanout(VirtIOGPU *g,
    598                                      uint32_t scanout_id,
    599                                      struct virtio_gpu_framebuffer *fb,
    600                                      struct virtio_gpu_simple_resource *res,
    601                                      struct virtio_gpu_rect *r,
    602                                      uint32_t *error)
    603{
    604    struct virtio_gpu_scanout *scanout;
    605    uint8_t *data;
    606
    607    scanout = &g->parent_obj.scanout[scanout_id];
    608
    609    if (r->x > fb->width ||
    610        r->y > fb->height ||
    611        r->width < 16 ||
    612        r->height < 16 ||
    613        r->width > fb->width ||
    614        r->height > fb->height ||
    615        r->x + r->width > fb->width ||
    616        r->y + r->height > fb->height) {
    617        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
    618                      " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
    619                      __func__, scanout_id, res->resource_id,
    620                      r->x, r->y, r->width, r->height,
    621                      fb->width, fb->height);
    622        *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
    623        return;
    624    }
    625
    626    g->parent_obj.enable = 1;
    627
    628    if (res->blob) {
    629        if (console_has_gl(scanout->con)) {
    630            if (!virtio_gpu_update_dmabuf(g, scanout_id, res, fb)) {
    631                virtio_gpu_update_scanout(g, scanout_id, res, r);
    632                return;
    633            }
    634        }
    635
    636        data = res->blob;
    637    } else {
    638        data = (uint8_t *)pixman_image_get_data(res->image);
    639    }
    640
    641    /* create a surface for this scanout */
    642    if ((res->blob && !console_has_gl(scanout->con)) ||
    643        !scanout->ds ||
    644        surface_data(scanout->ds) != data + fb->offset ||
    645        scanout->width != r->width ||
    646        scanout->height != r->height) {
    647        pixman_image_t *rect;
    648        void *ptr = data + fb->offset;
    649        rect = pixman_image_create_bits(fb->format, r->width, r->height,
    650                                        ptr, fb->stride);
    651
    652        if (res->image) {
    653            pixman_image_ref(res->image);
    654            pixman_image_set_destroy_function(rect, virtio_unref_resource,
    655                                              res->image);
    656        }
    657
    658        /* realloc the surface ptr */
    659        scanout->ds = qemu_create_displaysurface_pixman(rect);
    660        if (!scanout->ds) {
    661            *error = VIRTIO_GPU_RESP_ERR_UNSPEC;
    662            return;
    663        }
    664
    665        pixman_image_unref(rect);
    666        dpy_gfx_replace_surface(g->parent_obj.scanout[scanout_id].con,
    667                                scanout->ds);
    668    }
    669
    670    virtio_gpu_update_scanout(g, scanout_id, res, r);
    671}
    672
    673static void virtio_gpu_set_scanout(VirtIOGPU *g,
    674                                   struct virtio_gpu_ctrl_command *cmd)
    675{
    676    struct virtio_gpu_simple_resource *res;
    677    struct virtio_gpu_framebuffer fb = { 0 };
    678    struct virtio_gpu_set_scanout ss;
    679
    680    VIRTIO_GPU_FILL_CMD(ss);
    681    virtio_gpu_bswap_32(&ss, sizeof(ss));
    682    trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id,
    683                                     ss.r.width, ss.r.height, ss.r.x, ss.r.y);
    684
    685    if (ss.scanout_id >= g->parent_obj.conf.max_outputs) {
    686        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
    687                      __func__, ss.scanout_id);
    688        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
    689        return;
    690    }
    691
    692    if (ss.resource_id == 0) {
    693        virtio_gpu_disable_scanout(g, ss.scanout_id);
    694        return;
    695    }
    696
    697    res = virtio_gpu_find_check_resource(g, ss.resource_id, true,
    698                                         __func__, &cmd->error);
    699    if (!res) {
    700        return;
    701    }
    702
    703    fb.format = pixman_image_get_format(res->image);
    704    fb.bytes_pp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(fb.format), 8);
    705    fb.width  = pixman_image_get_width(res->image);
    706    fb.height = pixman_image_get_height(res->image);
    707    fb.stride = pixman_image_get_stride(res->image);
    708    fb.offset = ss.r.x * fb.bytes_pp + ss.r.y * fb.stride;
    709
    710    virtio_gpu_do_set_scanout(g, ss.scanout_id,
    711                              &fb, res, &ss.r, &cmd->error);
    712}
    713
    714static void virtio_gpu_set_scanout_blob(VirtIOGPU *g,
    715                                        struct virtio_gpu_ctrl_command *cmd)
    716{
    717    struct virtio_gpu_simple_resource *res;
    718    struct virtio_gpu_framebuffer fb = { 0 };
    719    struct virtio_gpu_set_scanout_blob ss;
    720    uint64_t fbend;
    721
    722    VIRTIO_GPU_FILL_CMD(ss);
    723    virtio_gpu_scanout_blob_bswap(&ss);
    724    trace_virtio_gpu_cmd_set_scanout_blob(ss.scanout_id, ss.resource_id,
    725                                          ss.r.width, ss.r.height, ss.r.x,
    726                                          ss.r.y);
    727
    728    if (ss.scanout_id >= g->parent_obj.conf.max_outputs) {
    729        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
    730                      __func__, ss.scanout_id);
    731        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
    732        return;
    733    }
    734
    735    if (ss.resource_id == 0) {
    736        virtio_gpu_disable_scanout(g, ss.scanout_id);
    737        return;
    738    }
    739
    740    res = virtio_gpu_find_check_resource(g, ss.resource_id, true,
    741                                         __func__, &cmd->error);
    742    if (!res) {
    743        return;
    744    }
    745
    746    fb.format = virtio_gpu_get_pixman_format(ss.format);
    747    if (!fb.format) {
    748        qemu_log_mask(LOG_GUEST_ERROR,
    749                      "%s: host couldn't handle guest format %d\n",
    750                      __func__, ss.format);
    751        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
    752        return;
    753    }
    754
    755    fb.bytes_pp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(fb.format), 8);
    756    fb.width = ss.width;
    757    fb.height = ss.height;
    758    fb.stride = ss.strides[0];
    759    fb.offset = ss.offsets[0] + ss.r.x * fb.bytes_pp + ss.r.y * fb.stride;
    760
    761    fbend = fb.offset;
    762    fbend += fb.stride * (ss.r.height - 1);
    763    fbend += fb.bytes_pp * ss.r.width;
    764    if (fbend > res->blob_size) {
    765        qemu_log_mask(LOG_GUEST_ERROR,
    766                      "%s: fb end out of range\n",
    767                      __func__);
    768        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
    769        return;
    770    }
    771
    772    virtio_gpu_do_set_scanout(g, ss.scanout_id,
    773                              &fb, res, &ss.r, &cmd->error);
    774}
    775
    776int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
    777                                  uint32_t nr_entries, uint32_t offset,
    778                                  struct virtio_gpu_ctrl_command *cmd,
    779                                  uint64_t **addr, struct iovec **iov,
    780                                  uint32_t *niov)
    781{
    782    struct virtio_gpu_mem_entry *ents;
    783    size_t esize, s;
    784    int e, v;
    785
    786    if (nr_entries > 16384) {
    787        qemu_log_mask(LOG_GUEST_ERROR,
    788                      "%s: nr_entries is too big (%d > 16384)\n",
    789                      __func__, nr_entries);
    790        return -1;
    791    }
    792
    793    esize = sizeof(*ents) * nr_entries;
    794    ents = g_malloc(esize);
    795    s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
    796                   offset, ents, esize);
    797    if (s != esize) {
    798        qemu_log_mask(LOG_GUEST_ERROR,
    799                      "%s: command data size incorrect %zu vs %zu\n",
    800                      __func__, s, esize);
    801        g_free(ents);
    802        return -1;
    803    }
    804
    805    *iov = NULL;
    806    if (addr) {
    807        *addr = NULL;
    808    }
    809    for (e = 0, v = 0; e < nr_entries; e++) {
    810        uint64_t a = le64_to_cpu(ents[e].addr);
    811        uint32_t l = le32_to_cpu(ents[e].length);
    812        hwaddr len;
    813        void *map;
    814
    815        do {
    816            len = l;
    817            map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as,
    818                                 a, &len, DMA_DIRECTION_TO_DEVICE);
    819            if (!map) {
    820                qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
    821                              " element %d\n", __func__, e);
    822                virtio_gpu_cleanup_mapping_iov(g, *iov, v);
    823                g_free(ents);
    824                *iov = NULL;
    825                if (addr) {
    826                    g_free(*addr);
    827                    *addr = NULL;
    828                }
    829                return -1;
    830            }
    831
    832            if (!(v % 16)) {
    833                *iov = g_realloc(*iov, sizeof(struct iovec) * (v + 16));
    834                if (addr) {
    835                    *addr = g_realloc(*addr, sizeof(uint64_t) * (v + 16));
    836                }
    837            }
    838            (*iov)[v].iov_base = map;
    839            (*iov)[v].iov_len = len;
    840            if (addr) {
    841                (*addr)[v] = a;
    842            }
    843
    844            a += len;
    845            l -= len;
    846            v += 1;
    847        } while (l > 0);
    848    }
    849    *niov = v;
    850
    851    g_free(ents);
    852    return 0;
    853}
    854
    855void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g,
    856                                    struct iovec *iov, uint32_t count)
    857{
    858    int i;
    859
    860    for (i = 0; i < count; i++) {
    861        dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as,
    862                         iov[i].iov_base, iov[i].iov_len,
    863                         DMA_DIRECTION_TO_DEVICE,
    864                         iov[i].iov_len);
    865    }
    866    g_free(iov);
    867}
    868
    869static void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
    870                                       struct virtio_gpu_simple_resource *res)
    871{
    872    virtio_gpu_cleanup_mapping_iov(g, res->iov, res->iov_cnt);
    873    res->iov = NULL;
    874    res->iov_cnt = 0;
    875    g_free(res->addrs);
    876    res->addrs = NULL;
    877
    878    if (res->blob) {
    879        virtio_gpu_fini_udmabuf(res);
    880    }
    881}
    882
    883static void
    884virtio_gpu_resource_attach_backing(VirtIOGPU *g,
    885                                   struct virtio_gpu_ctrl_command *cmd)
    886{
    887    struct virtio_gpu_simple_resource *res;
    888    struct virtio_gpu_resource_attach_backing ab;
    889    int ret;
    890
    891    VIRTIO_GPU_FILL_CMD(ab);
    892    virtio_gpu_bswap_32(&ab, sizeof(ab));
    893    trace_virtio_gpu_cmd_res_back_attach(ab.resource_id);
    894
    895    res = virtio_gpu_find_resource(g, ab.resource_id);
    896    if (!res) {
    897        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
    898                      __func__, ab.resource_id);
    899        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
    900        return;
    901    }
    902
    903    if (res->iov) {
    904        cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
    905        return;
    906    }
    907
    908    ret = virtio_gpu_create_mapping_iov(g, ab.nr_entries, sizeof(ab), cmd,
    909                                        &res->addrs, &res->iov, &res->iov_cnt);
    910    if (ret != 0) {
    911        cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
    912        return;
    913    }
    914}
    915
    916static void
    917virtio_gpu_resource_detach_backing(VirtIOGPU *g,
    918                                   struct virtio_gpu_ctrl_command *cmd)
    919{
    920    struct virtio_gpu_simple_resource *res;
    921    struct virtio_gpu_resource_detach_backing detach;
    922
    923    VIRTIO_GPU_FILL_CMD(detach);
    924    virtio_gpu_bswap_32(&detach, sizeof(detach));
    925    trace_virtio_gpu_cmd_res_back_detach(detach.resource_id);
    926
    927    res = virtio_gpu_find_check_resource(g, detach.resource_id, true,
    928                                         __func__, &cmd->error);
    929    if (!res) {
    930        return;
    931    }
    932    virtio_gpu_cleanup_mapping(g, res);
    933}
    934
    935void virtio_gpu_simple_process_cmd(VirtIOGPU *g,
    936                                   struct virtio_gpu_ctrl_command *cmd)
    937{
    938    VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr);
    939    virtio_gpu_ctrl_hdr_bswap(&cmd->cmd_hdr);
    940
    941    switch (cmd->cmd_hdr.type) {
    942    case VIRTIO_GPU_CMD_GET_DISPLAY_INFO:
    943        virtio_gpu_get_display_info(g, cmd);
    944        break;
    945    case VIRTIO_GPU_CMD_GET_EDID:
    946        virtio_gpu_get_edid(g, cmd);
    947        break;
    948    case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D:
    949        virtio_gpu_resource_create_2d(g, cmd);
    950        break;
    951    case VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB:
    952        if (!virtio_gpu_blob_enabled(g->parent_obj.conf)) {
    953            cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
    954            break;
    955        }
    956        virtio_gpu_resource_create_blob(g, cmd);
    957        break;
    958    case VIRTIO_GPU_CMD_RESOURCE_UNREF:
    959        virtio_gpu_resource_unref(g, cmd);
    960        break;
    961    case VIRTIO_GPU_CMD_RESOURCE_FLUSH:
    962        virtio_gpu_resource_flush(g, cmd);
    963        break;
    964    case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D:
    965        virtio_gpu_transfer_to_host_2d(g, cmd);
    966        break;
    967    case VIRTIO_GPU_CMD_SET_SCANOUT:
    968        virtio_gpu_set_scanout(g, cmd);
    969        break;
    970    case VIRTIO_GPU_CMD_SET_SCANOUT_BLOB:
    971        if (!virtio_gpu_blob_enabled(g->parent_obj.conf)) {
    972            cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
    973            break;
    974        }
    975        virtio_gpu_set_scanout_blob(g, cmd);
    976        break;
    977    case VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING:
    978        virtio_gpu_resource_attach_backing(g, cmd);
    979        break;
    980    case VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING:
    981        virtio_gpu_resource_detach_backing(g, cmd);
    982        break;
    983    default:
    984        cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
    985        break;
    986    }
    987    if (!cmd->finished) {
    988        if (!g->parent_obj.renderer_blocked) {
    989            virtio_gpu_ctrl_response_nodata(g, cmd, cmd->error ? cmd->error :
    990                                            VIRTIO_GPU_RESP_OK_NODATA);
    991        }
    992    }
    993}
    994
    995static void virtio_gpu_handle_ctrl_cb(VirtIODevice *vdev, VirtQueue *vq)
    996{
    997    VirtIOGPU *g = VIRTIO_GPU(vdev);
    998    qemu_bh_schedule(g->ctrl_bh);
    999}
   1000
   1001static void virtio_gpu_handle_cursor_cb(VirtIODevice *vdev, VirtQueue *vq)
   1002{
   1003    VirtIOGPU *g = VIRTIO_GPU(vdev);
   1004    qemu_bh_schedule(g->cursor_bh);
   1005}
   1006
   1007void virtio_gpu_process_cmdq(VirtIOGPU *g)
   1008{
   1009    struct virtio_gpu_ctrl_command *cmd;
   1010    VirtIOGPUClass *vgc = VIRTIO_GPU_GET_CLASS(g);
   1011
   1012    if (g->processing_cmdq) {
   1013        return;
   1014    }
   1015    g->processing_cmdq = true;
   1016    while (!QTAILQ_EMPTY(&g->cmdq)) {
   1017        cmd = QTAILQ_FIRST(&g->cmdq);
   1018
   1019        if (g->parent_obj.renderer_blocked) {
   1020            break;
   1021        }
   1022
   1023        /* process command */
   1024        vgc->process_cmd(g, cmd);
   1025
   1026        QTAILQ_REMOVE(&g->cmdq, cmd, next);
   1027        if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
   1028            g->stats.requests++;
   1029        }
   1030
   1031        if (!cmd->finished) {
   1032            QTAILQ_INSERT_TAIL(&g->fenceq, cmd, next);
   1033            g->inflight++;
   1034            if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
   1035                if (g->stats.max_inflight < g->inflight) {
   1036                    g->stats.max_inflight = g->inflight;
   1037                }
   1038                fprintf(stderr, "inflight: %3d (+)\r", g->inflight);
   1039            }
   1040        } else {
   1041            g_free(cmd);
   1042        }
   1043    }
   1044    g->processing_cmdq = false;
   1045}
   1046
   1047static void virtio_gpu_process_fenceq(VirtIOGPU *g)
   1048{
   1049    struct virtio_gpu_ctrl_command *cmd, *tmp;
   1050
   1051    QTAILQ_FOREACH_SAFE(cmd, &g->fenceq, next, tmp) {
   1052        trace_virtio_gpu_fence_resp(cmd->cmd_hdr.fence_id);
   1053        virtio_gpu_ctrl_response_nodata(g, cmd, VIRTIO_GPU_RESP_OK_NODATA);
   1054        QTAILQ_REMOVE(&g->fenceq, cmd, next);
   1055        g_free(cmd);
   1056        g->inflight--;
   1057        if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
   1058            fprintf(stderr, "inflight: %3d (-)\r", g->inflight);
   1059        }
   1060    }
   1061}
   1062
   1063static void virtio_gpu_handle_gl_flushed(VirtIOGPUBase *b)
   1064{
   1065    VirtIOGPU *g = container_of(b, VirtIOGPU, parent_obj);
   1066
   1067    virtio_gpu_process_fenceq(g);
   1068    virtio_gpu_process_cmdq(g);
   1069}
   1070
   1071static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
   1072{
   1073    VirtIOGPU *g = VIRTIO_GPU(vdev);
   1074    struct virtio_gpu_ctrl_command *cmd;
   1075
   1076    if (!virtio_queue_ready(vq)) {
   1077        return;
   1078    }
   1079
   1080    cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
   1081    while (cmd) {
   1082        cmd->vq = vq;
   1083        cmd->error = 0;
   1084        cmd->finished = false;
   1085        QTAILQ_INSERT_TAIL(&g->cmdq, cmd, next);
   1086        cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
   1087    }
   1088
   1089    virtio_gpu_process_cmdq(g);
   1090}
   1091
   1092static void virtio_gpu_ctrl_bh(void *opaque)
   1093{
   1094    VirtIOGPU *g = opaque;
   1095    VirtIOGPUClass *vgc = VIRTIO_GPU_GET_CLASS(g);
   1096
   1097    vgc->handle_ctrl(&g->parent_obj.parent_obj, g->ctrl_vq);
   1098}
   1099
   1100static void virtio_gpu_handle_cursor(VirtIODevice *vdev, VirtQueue *vq)
   1101{
   1102    VirtIOGPU *g = VIRTIO_GPU(vdev);
   1103    VirtQueueElement *elem;
   1104    size_t s;
   1105    struct virtio_gpu_update_cursor cursor_info;
   1106
   1107    if (!virtio_queue_ready(vq)) {
   1108        return;
   1109    }
   1110    for (;;) {
   1111        elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
   1112        if (!elem) {
   1113            break;
   1114        }
   1115
   1116        s = iov_to_buf(elem->out_sg, elem->out_num, 0,
   1117                       &cursor_info, sizeof(cursor_info));
   1118        if (s != sizeof(cursor_info)) {
   1119            qemu_log_mask(LOG_GUEST_ERROR,
   1120                          "%s: cursor size incorrect %zu vs %zu\n",
   1121                          __func__, s, sizeof(cursor_info));
   1122        } else {
   1123            virtio_gpu_bswap_32(&cursor_info, sizeof(cursor_info));
   1124            update_cursor(g, &cursor_info);
   1125        }
   1126        virtqueue_push(vq, elem, 0);
   1127        virtio_notify(vdev, vq);
   1128        g_free(elem);
   1129    }
   1130}
   1131
   1132static void virtio_gpu_cursor_bh(void *opaque)
   1133{
   1134    VirtIOGPU *g = opaque;
   1135    virtio_gpu_handle_cursor(&g->parent_obj.parent_obj, g->cursor_vq);
   1136}
   1137
   1138static const VMStateDescription vmstate_virtio_gpu_scanout = {
   1139    .name = "virtio-gpu-one-scanout",
   1140    .version_id = 1,
   1141    .fields = (VMStateField[]) {
   1142        VMSTATE_UINT32(resource_id, struct virtio_gpu_scanout),
   1143        VMSTATE_UINT32(width, struct virtio_gpu_scanout),
   1144        VMSTATE_UINT32(height, struct virtio_gpu_scanout),
   1145        VMSTATE_INT32(x, struct virtio_gpu_scanout),
   1146        VMSTATE_INT32(y, struct virtio_gpu_scanout),
   1147        VMSTATE_UINT32(cursor.resource_id, struct virtio_gpu_scanout),
   1148        VMSTATE_UINT32(cursor.hot_x, struct virtio_gpu_scanout),
   1149        VMSTATE_UINT32(cursor.hot_y, struct virtio_gpu_scanout),
   1150        VMSTATE_UINT32(cursor.pos.x, struct virtio_gpu_scanout),
   1151        VMSTATE_UINT32(cursor.pos.y, struct virtio_gpu_scanout),
   1152        VMSTATE_END_OF_LIST()
   1153    },
   1154};
   1155
   1156static const VMStateDescription vmstate_virtio_gpu_scanouts = {
   1157    .name = "virtio-gpu-scanouts",
   1158    .version_id = 1,
   1159    .fields = (VMStateField[]) {
   1160        VMSTATE_INT32(parent_obj.enable, struct VirtIOGPU),
   1161        VMSTATE_UINT32_EQUAL(parent_obj.conf.max_outputs,
   1162                             struct VirtIOGPU, NULL),
   1163        VMSTATE_STRUCT_VARRAY_UINT32(parent_obj.scanout, struct VirtIOGPU,
   1164                                     parent_obj.conf.max_outputs, 1,
   1165                                     vmstate_virtio_gpu_scanout,
   1166                                     struct virtio_gpu_scanout),
   1167        VMSTATE_END_OF_LIST()
   1168    },
   1169};
   1170
   1171static int virtio_gpu_save(QEMUFile *f, void *opaque, size_t size,
   1172                           const VMStateField *field, JSONWriter *vmdesc)
   1173{
   1174    VirtIOGPU *g = opaque;
   1175    struct virtio_gpu_simple_resource *res;
   1176    int i;
   1177
   1178    /* in 2d mode we should never find unprocessed commands here */
   1179    assert(QTAILQ_EMPTY(&g->cmdq));
   1180
   1181    QTAILQ_FOREACH(res, &g->reslist, next) {
   1182        qemu_put_be32(f, res->resource_id);
   1183        qemu_put_be32(f, res->width);
   1184        qemu_put_be32(f, res->height);
   1185        qemu_put_be32(f, res->format);
   1186        qemu_put_be32(f, res->iov_cnt);
   1187        for (i = 0; i < res->iov_cnt; i++) {
   1188            qemu_put_be64(f, res->addrs[i]);
   1189            qemu_put_be32(f, res->iov[i].iov_len);
   1190        }
   1191        qemu_put_buffer(f, (void *)pixman_image_get_data(res->image),
   1192                        pixman_image_get_stride(res->image) * res->height);
   1193    }
   1194    qemu_put_be32(f, 0); /* end of list */
   1195
   1196    return vmstate_save_state(f, &vmstate_virtio_gpu_scanouts, g, NULL);
   1197}
   1198
   1199static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
   1200                           const VMStateField *field)
   1201{
   1202    VirtIOGPU *g = opaque;
   1203    struct virtio_gpu_simple_resource *res;
   1204    struct virtio_gpu_scanout *scanout;
   1205    uint32_t resource_id, pformat;
   1206    int i;
   1207
   1208    g->hostmem = 0;
   1209
   1210    resource_id = qemu_get_be32(f);
   1211    while (resource_id != 0) {
   1212        res = virtio_gpu_find_resource(g, resource_id);
   1213        if (res) {
   1214            return -EINVAL;
   1215        }
   1216
   1217        res = g_new0(struct virtio_gpu_simple_resource, 1);
   1218        res->resource_id = resource_id;
   1219        res->width = qemu_get_be32(f);
   1220        res->height = qemu_get_be32(f);
   1221        res->format = qemu_get_be32(f);
   1222        res->iov_cnt = qemu_get_be32(f);
   1223
   1224        /* allocate */
   1225        pformat = virtio_gpu_get_pixman_format(res->format);
   1226        if (!pformat) {
   1227            g_free(res);
   1228            return -EINVAL;
   1229        }
   1230        res->image = pixman_image_create_bits(pformat,
   1231                                              res->width, res->height,
   1232                                              NULL, 0);
   1233        if (!res->image) {
   1234            g_free(res);
   1235            return -EINVAL;
   1236        }
   1237
   1238        res->hostmem = calc_image_hostmem(pformat, res->width, res->height);
   1239
   1240        res->addrs = g_new(uint64_t, res->iov_cnt);
   1241        res->iov = g_new(struct iovec, res->iov_cnt);
   1242
   1243        /* read data */
   1244        for (i = 0; i < res->iov_cnt; i++) {
   1245            res->addrs[i] = qemu_get_be64(f);
   1246            res->iov[i].iov_len = qemu_get_be32(f);
   1247        }
   1248        qemu_get_buffer(f, (void *)pixman_image_get_data(res->image),
   1249                        pixman_image_get_stride(res->image) * res->height);
   1250
   1251        /* restore mapping */
   1252        for (i = 0; i < res->iov_cnt; i++) {
   1253            hwaddr len = res->iov[i].iov_len;
   1254            res->iov[i].iov_base =
   1255                dma_memory_map(VIRTIO_DEVICE(g)->dma_as,
   1256                               res->addrs[i], &len, DMA_DIRECTION_TO_DEVICE);
   1257
   1258            if (!res->iov[i].iov_base || len != res->iov[i].iov_len) {
   1259                /* Clean up the half-a-mapping we just created... */
   1260                if (res->iov[i].iov_base) {
   1261                    dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as,
   1262                                     res->iov[i].iov_base,
   1263                                     len,
   1264                                     DMA_DIRECTION_TO_DEVICE,
   1265                                     0);
   1266                }
   1267                /* ...and the mappings for previous loop iterations */
   1268                res->iov_cnt = i;
   1269                virtio_gpu_cleanup_mapping(g, res);
   1270                pixman_image_unref(res->image);
   1271                g_free(res);
   1272                return -EINVAL;
   1273            }
   1274        }
   1275
   1276        QTAILQ_INSERT_HEAD(&g->reslist, res, next);
   1277        g->hostmem += res->hostmem;
   1278
   1279        resource_id = qemu_get_be32(f);
   1280    }
   1281
   1282    /* load & apply scanout state */
   1283    vmstate_load_state(f, &vmstate_virtio_gpu_scanouts, g, 1);
   1284    for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
   1285        scanout = &g->parent_obj.scanout[i];
   1286        if (!scanout->resource_id) {
   1287            continue;
   1288        }
   1289        res = virtio_gpu_find_resource(g, scanout->resource_id);
   1290        if (!res) {
   1291            return -EINVAL;
   1292        }
   1293        scanout->ds = qemu_create_displaysurface_pixman(res->image);
   1294        if (!scanout->ds) {
   1295            return -EINVAL;
   1296        }
   1297
   1298        dpy_gfx_replace_surface(scanout->con, scanout->ds);
   1299        dpy_gfx_update_full(scanout->con);
   1300        if (scanout->cursor.resource_id) {
   1301            update_cursor(g, &scanout->cursor);
   1302        }
   1303        res->scanout_bitmask |= (1 << i);
   1304    }
   1305
   1306    return 0;
   1307}
   1308
   1309void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
   1310{
   1311    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
   1312    VirtIOGPU *g = VIRTIO_GPU(qdev);
   1313
   1314    if (virtio_gpu_blob_enabled(g->parent_obj.conf)) {
   1315        if (!virtio_gpu_have_udmabuf()) {
   1316            error_setg(errp, "cannot enable blob resources without udmabuf");
   1317            return;
   1318        }
   1319
   1320        if (virtio_gpu_virgl_enabled(g->parent_obj.conf)) {
   1321            error_setg(errp, "blobs and virgl are not compatible (yet)");
   1322            return;
   1323        }
   1324    }
   1325
   1326    if (!virtio_gpu_base_device_realize(qdev,
   1327                                        virtio_gpu_handle_ctrl_cb,
   1328                                        virtio_gpu_handle_cursor_cb,
   1329                                        errp)) {
   1330        return;
   1331    }
   1332
   1333    g->ctrl_vq = virtio_get_queue(vdev, 0);
   1334    g->cursor_vq = virtio_get_queue(vdev, 1);
   1335    g->ctrl_bh = qemu_bh_new(virtio_gpu_ctrl_bh, g);
   1336    g->cursor_bh = qemu_bh_new(virtio_gpu_cursor_bh, g);
   1337    QTAILQ_INIT(&g->reslist);
   1338    QTAILQ_INIT(&g->cmdq);
   1339    QTAILQ_INIT(&g->fenceq);
   1340}
   1341
   1342void virtio_gpu_reset(VirtIODevice *vdev)
   1343{
   1344    VirtIOGPU *g = VIRTIO_GPU(vdev);
   1345    struct virtio_gpu_simple_resource *res, *tmp;
   1346    struct virtio_gpu_ctrl_command *cmd;
   1347
   1348    QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) {
   1349        virtio_gpu_resource_destroy(g, res);
   1350    }
   1351
   1352    while (!QTAILQ_EMPTY(&g->cmdq)) {
   1353        cmd = QTAILQ_FIRST(&g->cmdq);
   1354        QTAILQ_REMOVE(&g->cmdq, cmd, next);
   1355        g_free(cmd);
   1356    }
   1357
   1358    while (!QTAILQ_EMPTY(&g->fenceq)) {
   1359        cmd = QTAILQ_FIRST(&g->fenceq);
   1360        QTAILQ_REMOVE(&g->fenceq, cmd, next);
   1361        g->inflight--;
   1362        g_free(cmd);
   1363    }
   1364
   1365    virtio_gpu_base_reset(VIRTIO_GPU_BASE(vdev));
   1366}
   1367
   1368static void
   1369virtio_gpu_get_config(VirtIODevice *vdev, uint8_t *config)
   1370{
   1371    VirtIOGPUBase *g = VIRTIO_GPU_BASE(vdev);
   1372
   1373    memcpy(config, &g->virtio_config, sizeof(g->virtio_config));
   1374}
   1375
   1376static void
   1377virtio_gpu_set_config(VirtIODevice *vdev, const uint8_t *config)
   1378{
   1379    VirtIOGPUBase *g = VIRTIO_GPU_BASE(vdev);
   1380    const struct virtio_gpu_config *vgconfig =
   1381        (const struct virtio_gpu_config *)config;
   1382
   1383    if (vgconfig->events_clear) {
   1384        g->virtio_config.events_read &= ~vgconfig->events_clear;
   1385    }
   1386}
   1387
   1388/*
   1389 * For historical reasons virtio_gpu does not adhere to virtio migration
   1390 * scheme as described in doc/virtio-migration.txt, in a sense that no
   1391 * save/load callback are provided to the core. Instead the device data
   1392 * is saved/loaded after the core data.
   1393 *
   1394 * Because of this we need a special vmsd.
   1395 */
   1396static const VMStateDescription vmstate_virtio_gpu = {
   1397    .name = "virtio-gpu",
   1398    .minimum_version_id = VIRTIO_GPU_VM_VERSION,
   1399    .version_id = VIRTIO_GPU_VM_VERSION,
   1400    .fields = (VMStateField[]) {
   1401        VMSTATE_VIRTIO_DEVICE /* core */,
   1402        {
   1403            .name = "virtio-gpu",
   1404            .info = &(const VMStateInfo) {
   1405                        .name = "virtio-gpu",
   1406                        .get = virtio_gpu_load,
   1407                        .put = virtio_gpu_save,
   1408            },
   1409            .flags = VMS_SINGLE,
   1410        } /* device */,
   1411        VMSTATE_END_OF_LIST()
   1412    },
   1413};
   1414
   1415static Property virtio_gpu_properties[] = {
   1416    VIRTIO_GPU_BASE_PROPERTIES(VirtIOGPU, parent_obj.conf),
   1417    DEFINE_PROP_SIZE("max_hostmem", VirtIOGPU, conf_max_hostmem,
   1418                     256 * MiB),
   1419    DEFINE_PROP_BIT("blob", VirtIOGPU, parent_obj.conf.flags,
   1420                    VIRTIO_GPU_FLAG_BLOB_ENABLED, false),
   1421    DEFINE_PROP_END_OF_LIST(),
   1422};
   1423
   1424static void virtio_gpu_class_init(ObjectClass *klass, void *data)
   1425{
   1426    DeviceClass *dc = DEVICE_CLASS(klass);
   1427    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
   1428    VirtIOGPUClass *vgc = VIRTIO_GPU_CLASS(klass);
   1429    VirtIOGPUBaseClass *vgbc = &vgc->parent;
   1430
   1431    vgc->handle_ctrl = virtio_gpu_handle_ctrl;
   1432    vgc->process_cmd = virtio_gpu_simple_process_cmd;
   1433    vgc->update_cursor_data = virtio_gpu_update_cursor_data;
   1434    vgbc->gl_flushed = virtio_gpu_handle_gl_flushed;
   1435
   1436    vdc->realize = virtio_gpu_device_realize;
   1437    vdc->reset = virtio_gpu_reset;
   1438    vdc->get_config = virtio_gpu_get_config;
   1439    vdc->set_config = virtio_gpu_set_config;
   1440
   1441    dc->vmsd = &vmstate_virtio_gpu;
   1442    device_class_set_props(dc, virtio_gpu_properties);
   1443}
   1444
   1445static const TypeInfo virtio_gpu_info = {
   1446    .name = TYPE_VIRTIO_GPU,
   1447    .parent = TYPE_VIRTIO_GPU_BASE,
   1448    .instance_size = sizeof(VirtIOGPU),
   1449    .class_size = sizeof(VirtIOGPUClass),
   1450    .class_init = virtio_gpu_class_init,
   1451};
   1452module_obj(TYPE_VIRTIO_GPU);
   1453
   1454static void virtio_register_types(void)
   1455{
   1456    type_register_static(&virtio_gpu_info);
   1457}
   1458
   1459type_init(virtio_register_types)