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-base.c (8422B)


      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
     16#include "hw/virtio/virtio-gpu.h"
     17#include "migration/blocker.h"
     18#include "qapi/error.h"
     19#include "qemu/error-report.h"
     20#include "trace.h"
     21
     22void
     23virtio_gpu_base_reset(VirtIOGPUBase *g)
     24{
     25    int i;
     26
     27    g->enable = 0;
     28
     29    for (i = 0; i < g->conf.max_outputs; i++) {
     30        g->scanout[i].resource_id = 0;
     31        g->scanout[i].width = 0;
     32        g->scanout[i].height = 0;
     33        g->scanout[i].x = 0;
     34        g->scanout[i].y = 0;
     35        g->scanout[i].ds = NULL;
     36    }
     37}
     38
     39void
     40virtio_gpu_base_fill_display_info(VirtIOGPUBase *g,
     41                                  struct virtio_gpu_resp_display_info *dpy_info)
     42{
     43    int i;
     44
     45    for (i = 0; i < g->conf.max_outputs; i++) {
     46        if (g->enabled_output_bitmask & (1 << i)) {
     47            dpy_info->pmodes[i].enabled = 1;
     48            dpy_info->pmodes[i].r.width = cpu_to_le32(g->req_state[i].width);
     49            dpy_info->pmodes[i].r.height = cpu_to_le32(g->req_state[i].height);
     50        }
     51    }
     52}
     53
     54static void virtio_gpu_invalidate_display(void *opaque)
     55{
     56}
     57
     58static void virtio_gpu_update_display(void *opaque)
     59{
     60}
     61
     62static void virtio_gpu_text_update(void *opaque, console_ch_t *chardata)
     63{
     64}
     65
     66static void virtio_gpu_notify_event(VirtIOGPUBase *g, uint32_t event_type)
     67{
     68    g->virtio_config.events_read |= event_type;
     69    virtio_notify_config(&g->parent_obj);
     70}
     71
     72static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
     73{
     74    VirtIOGPUBase *g = opaque;
     75
     76    if (idx >= g->conf.max_outputs) {
     77        return -1;
     78    }
     79
     80    g->req_state[idx].x = info->xoff;
     81    g->req_state[idx].y = info->yoff;
     82    g->req_state[idx].width = info->width;
     83    g->req_state[idx].height = info->height;
     84    g->req_state[idx].width_mm = info->width_mm;
     85    g->req_state[idx].height_mm = info->height_mm;
     86
     87    if (info->width && info->height) {
     88        g->enabled_output_bitmask |= (1 << idx);
     89    } else {
     90        g->enabled_output_bitmask &= ~(1 << idx);
     91    }
     92
     93    /* send event to guest */
     94    virtio_gpu_notify_event(g, VIRTIO_GPU_EVENT_DISPLAY);
     95    return 0;
     96}
     97
     98static void
     99virtio_gpu_gl_flushed(void *opaque)
    100{
    101    VirtIOGPUBase *g = opaque;
    102    VirtIOGPUBaseClass *vgc = VIRTIO_GPU_BASE_GET_CLASS(g);
    103
    104    if (vgc->gl_flushed) {
    105        vgc->gl_flushed(g);
    106    }
    107}
    108
    109static void
    110virtio_gpu_gl_block(void *opaque, bool block)
    111{
    112    VirtIOGPUBase *g = opaque;
    113
    114    if (block) {
    115        g->renderer_blocked++;
    116    } else {
    117        g->renderer_blocked--;
    118    }
    119    assert(g->renderer_blocked >= 0);
    120}
    121
    122static int
    123virtio_gpu_get_flags(void *opaque)
    124{
    125    VirtIOGPUBase *g = opaque;
    126    int flags = GRAPHIC_FLAGS_NONE;
    127
    128    if (virtio_gpu_virgl_enabled(g->conf)) {
    129        flags |= GRAPHIC_FLAGS_GL;
    130    }
    131
    132    if (virtio_gpu_dmabuf_enabled(g->conf)) {
    133        flags |= GRAPHIC_FLAGS_DMABUF;
    134    }
    135
    136    return flags;
    137}
    138
    139static const GraphicHwOps virtio_gpu_ops = {
    140    .get_flags = virtio_gpu_get_flags,
    141    .invalidate = virtio_gpu_invalidate_display,
    142    .gfx_update = virtio_gpu_update_display,
    143    .text_update = virtio_gpu_text_update,
    144    .ui_info = virtio_gpu_ui_info,
    145    .gl_block = virtio_gpu_gl_block,
    146    .gl_flushed = virtio_gpu_gl_flushed,
    147};
    148
    149bool
    150virtio_gpu_base_device_realize(DeviceState *qdev,
    151                               VirtIOHandleOutput ctrl_cb,
    152                               VirtIOHandleOutput cursor_cb,
    153                               Error **errp)
    154{
    155    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
    156    VirtIOGPUBase *g = VIRTIO_GPU_BASE(qdev);
    157    int i;
    158
    159    if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) {
    160        error_setg(errp, "invalid max_outputs > %d", VIRTIO_GPU_MAX_SCANOUTS);
    161        return false;
    162    }
    163
    164    if (virtio_gpu_virgl_enabled(g->conf)) {
    165        error_setg(&g->migration_blocker, "virgl is not yet migratable");
    166        if (migrate_add_blocker(g->migration_blocker, errp) < 0) {
    167            error_free(g->migration_blocker);
    168            return false;
    169        }
    170    }
    171
    172    g->virtio_config.num_scanouts = cpu_to_le32(g->conf.max_outputs);
    173    virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
    174                sizeof(struct virtio_gpu_config));
    175
    176    if (virtio_gpu_virgl_enabled(g->conf)) {
    177        /* use larger control queue in 3d mode */
    178        virtio_add_queue(vdev, 256, ctrl_cb);
    179        virtio_add_queue(vdev, 16, cursor_cb);
    180    } else {
    181        virtio_add_queue(vdev, 64, ctrl_cb);
    182        virtio_add_queue(vdev, 16, cursor_cb);
    183    }
    184
    185    g->enabled_output_bitmask = 1;
    186
    187    g->req_state[0].width = g->conf.xres;
    188    g->req_state[0].height = g->conf.yres;
    189
    190    g->hw_ops = &virtio_gpu_ops;
    191    for (i = 0; i < g->conf.max_outputs; i++) {
    192        g->scanout[i].con =
    193            graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g);
    194    }
    195
    196    return true;
    197}
    198
    199static uint64_t
    200virtio_gpu_base_get_features(VirtIODevice *vdev, uint64_t features,
    201                             Error **errp)
    202{
    203    VirtIOGPUBase *g = VIRTIO_GPU_BASE(vdev);
    204
    205    if (virtio_gpu_virgl_enabled(g->conf)) {
    206        features |= (1 << VIRTIO_GPU_F_VIRGL);
    207    }
    208    if (virtio_gpu_edid_enabled(g->conf)) {
    209        features |= (1 << VIRTIO_GPU_F_EDID);
    210    }
    211    if (virtio_gpu_blob_enabled(g->conf)) {
    212        features |= (1 << VIRTIO_GPU_F_RESOURCE_BLOB);
    213    }
    214
    215    return features;
    216}
    217
    218static void
    219virtio_gpu_base_set_features(VirtIODevice *vdev, uint64_t features)
    220{
    221    static const uint32_t virgl = (1 << VIRTIO_GPU_F_VIRGL);
    222
    223    trace_virtio_gpu_features(((features & virgl) == virgl));
    224}
    225
    226static void
    227virtio_gpu_base_device_unrealize(DeviceState *qdev)
    228{
    229    VirtIOGPUBase *g = VIRTIO_GPU_BASE(qdev);
    230
    231    if (g->migration_blocker) {
    232        migrate_del_blocker(g->migration_blocker);
    233        error_free(g->migration_blocker);
    234    }
    235}
    236
    237static void
    238virtio_gpu_base_class_init(ObjectClass *klass, void *data)
    239{
    240    DeviceClass *dc = DEVICE_CLASS(klass);
    241    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
    242
    243    vdc->unrealize = virtio_gpu_base_device_unrealize;
    244    vdc->get_features = virtio_gpu_base_get_features;
    245    vdc->set_features = virtio_gpu_base_set_features;
    246
    247    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
    248    dc->hotpluggable = false;
    249}
    250
    251static const TypeInfo virtio_gpu_base_info = {
    252    .name = TYPE_VIRTIO_GPU_BASE,
    253    .parent = TYPE_VIRTIO_DEVICE,
    254    .instance_size = sizeof(VirtIOGPUBase),
    255    .class_size = sizeof(VirtIOGPUBaseClass),
    256    .class_init = virtio_gpu_base_class_init,
    257    .abstract = true
    258};
    259module_obj(TYPE_VIRTIO_GPU_BASE);
    260
    261static void
    262virtio_register_types(void)
    263{
    264    type_register_static(&virtio_gpu_base_info);
    265}
    266
    267type_init(virtio_register_types)
    268
    269QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctrl_hdr)                != 24);
    270QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_update_cursor)           != 56);
    271QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_unref)          != 32);
    272QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_2d)      != 40);
    273QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_set_scanout)             != 48);
    274QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_flush)          != 48);
    275QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_to_host_2d)     != 56);
    276QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_mem_entry)               != 16);
    277QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_attach_backing) != 32);
    278QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_detach_backing) != 32);
    279QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_display_info)       != 408);
    280
    281QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_host_3d)        != 72);
    282QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_3d)      != 72);
    283QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_create)              != 96);
    284QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_destroy)             != 24);
    285QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_resource)            != 32);
    286QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_cmd_submit)              != 32);
    287QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset_info)         != 32);
    288QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset_info)        != 40);
    289QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset)              != 32);
    290QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset)             != 24);