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

qxl-logger.c (8895B)


      1/*
      2 * qxl command logging -- for debug purposes
      3 *
      4 * Copyright (C) 2010 Red Hat, Inc.
      5 *
      6 * maintained by Gerd Hoffmann <kraxel@redhat.com>
      7 *
      8 * This program is free software; you can redistribute it and/or
      9 * modify it under the terms of the GNU General Public License as
     10 * published by the Free Software Foundation; either version 2 or
     11 * (at your option) version 3 of the License.
     12 *
     13 * This program is distributed in the hope that it will be useful,
     14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 * GNU General Public License for more details.
     17 *
     18 * You should have received a copy of the GNU General Public License
     19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
     20 */
     21
     22#include "qemu/osdep.h"
     23#include "qemu/timer.h"
     24#include "qxl.h"
     25
     26static const char *const qxl_type[] = {
     27    [ QXL_CMD_NOP ]     = "nop",
     28    [ QXL_CMD_DRAW ]    = "draw",
     29    [ QXL_CMD_UPDATE ]  = "update",
     30    [ QXL_CMD_CURSOR ]  = "cursor",
     31    [ QXL_CMD_MESSAGE ] = "message",
     32    [ QXL_CMD_SURFACE ] = "surface",
     33};
     34
     35static const char *const qxl_draw_type[] = {
     36    [ QXL_DRAW_NOP         ] = "nop",
     37    [ QXL_DRAW_FILL        ] = "fill",
     38    [ QXL_DRAW_OPAQUE      ] = "opaque",
     39    [ QXL_DRAW_COPY        ] = "copy",
     40    [ QXL_COPY_BITS        ] = "copy-bits",
     41    [ QXL_DRAW_BLEND       ] = "blend",
     42    [ QXL_DRAW_BLACKNESS   ] = "blackness",
     43    [ QXL_DRAW_WHITENESS   ] = "whitemess",
     44    [ QXL_DRAW_INVERS      ] = "invers",
     45    [ QXL_DRAW_ROP3        ] = "rop3",
     46    [ QXL_DRAW_STROKE      ] = "stroke",
     47    [ QXL_DRAW_TEXT        ] = "text",
     48    [ QXL_DRAW_TRANSPARENT ] = "transparent",
     49    [ QXL_DRAW_ALPHA_BLEND ] = "alpha-blend",
     50};
     51
     52static const char *const qxl_draw_effect[] = {
     53    [ QXL_EFFECT_BLEND            ] = "blend",
     54    [ QXL_EFFECT_OPAQUE           ] = "opaque",
     55    [ QXL_EFFECT_REVERT_ON_DUP    ] = "revert-on-dup",
     56    [ QXL_EFFECT_BLACKNESS_ON_DUP ] = "blackness-on-dup",
     57    [ QXL_EFFECT_WHITENESS_ON_DUP ] = "whiteness-on-dup",
     58    [ QXL_EFFECT_NOP_ON_DUP       ] = "nop-on-dup",
     59    [ QXL_EFFECT_NOP              ] = "nop",
     60    [ QXL_EFFECT_OPAQUE_BRUSH     ] = "opaque-brush",
     61};
     62
     63static const char *const qxl_surface_cmd[] = {
     64   [ QXL_SURFACE_CMD_CREATE  ] = "create",
     65   [ QXL_SURFACE_CMD_DESTROY ] = "destroy",
     66};
     67
     68static const char *const spice_surface_fmt[] = {
     69   [ SPICE_SURFACE_FMT_INVALID  ] = "invalid",
     70   [ SPICE_SURFACE_FMT_1_A      ] = "alpha/1",
     71   [ SPICE_SURFACE_FMT_8_A      ] = "alpha/8",
     72   [ SPICE_SURFACE_FMT_16_555   ] = "555/16",
     73   [ SPICE_SURFACE_FMT_16_565   ] = "565/16",
     74   [ SPICE_SURFACE_FMT_32_xRGB  ] = "xRGB/32",
     75   [ SPICE_SURFACE_FMT_32_ARGB  ] = "ARGB/32",
     76};
     77
     78static const char *const qxl_cursor_cmd[] = {
     79   [ QXL_CURSOR_SET   ] = "set",
     80   [ QXL_CURSOR_MOVE  ] = "move",
     81   [ QXL_CURSOR_HIDE  ] = "hide",
     82   [ QXL_CURSOR_TRAIL ] = "trail",
     83};
     84
     85static const char *const spice_cursor_type[] = {
     86   [ SPICE_CURSOR_TYPE_ALPHA   ] = "alpha",
     87   [ SPICE_CURSOR_TYPE_MONO    ] = "mono",
     88   [ SPICE_CURSOR_TYPE_COLOR4  ] = "color4",
     89   [ SPICE_CURSOR_TYPE_COLOR8  ] = "color8",
     90   [ SPICE_CURSOR_TYPE_COLOR16 ] = "color16",
     91   [ SPICE_CURSOR_TYPE_COLOR24 ] = "color24",
     92   [ SPICE_CURSOR_TYPE_COLOR32 ] = "color32",
     93};
     94
     95static const char *qxl_v2n(const char *const n[], size_t l, int v)
     96{
     97    if (v >= l || !n[v]) {
     98        return "???";
     99    }
    100    return n[v];
    101}
    102#define qxl_name(_list, _value) qxl_v2n(_list, ARRAY_SIZE(_list), _value)
    103
    104static int qxl_log_image(PCIQXLDevice *qxl, QXLPHYSICAL addr, int group_id)
    105{
    106    QXLImage *image;
    107    QXLImageDescriptor *desc;
    108
    109    image = qxl_phys2virt(qxl, addr, group_id);
    110    if (!image) {
    111        return 1;
    112    }
    113    desc = &image->descriptor;
    114    fprintf(stderr, " (id %" PRIx64 " type %d flags %d width %d height %d",
    115            desc->id, desc->type, desc->flags, desc->width, desc->height);
    116    switch (desc->type) {
    117    case SPICE_IMAGE_TYPE_BITMAP:
    118        fprintf(stderr, ", fmt %d flags %d x %d y %d stride %d"
    119                " palette %" PRIx64 " data %" PRIx64,
    120                image->bitmap.format, image->bitmap.flags,
    121                image->bitmap.x, image->bitmap.y,
    122                image->bitmap.stride,
    123                image->bitmap.palette, image->bitmap.data);
    124        break;
    125    }
    126    fprintf(stderr, ")");
    127    return 0;
    128}
    129
    130static void qxl_log_rect(QXLRect *rect)
    131{
    132    fprintf(stderr, " %dx%d+%d+%d",
    133            rect->right - rect->left,
    134            rect->bottom - rect->top,
    135            rect->left, rect->top);
    136}
    137
    138static int qxl_log_cmd_draw_copy(PCIQXLDevice *qxl, QXLCopy *copy,
    139                                 int group_id)
    140{
    141    int ret;
    142
    143    fprintf(stderr, " src %" PRIx64,
    144            copy->src_bitmap);
    145    ret = qxl_log_image(qxl, copy->src_bitmap, group_id);
    146    if (ret != 0) {
    147        return ret;
    148    }
    149    fprintf(stderr, " area");
    150    qxl_log_rect(&copy->src_area);
    151    fprintf(stderr, " rop %d", copy->rop_descriptor);
    152    return 0;
    153}
    154
    155static int qxl_log_cmd_draw(PCIQXLDevice *qxl, QXLDrawable *draw, int group_id)
    156{
    157    fprintf(stderr, ": surface_id %d type %s effect %s",
    158            draw->surface_id,
    159            qxl_name(qxl_draw_type, draw->type),
    160            qxl_name(qxl_draw_effect, draw->effect));
    161    switch (draw->type) {
    162    case QXL_DRAW_COPY:
    163        return qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id);
    164    }
    165    return 0;
    166}
    167
    168static int qxl_log_cmd_draw_compat(PCIQXLDevice *qxl, QXLCompatDrawable *draw,
    169                                   int group_id)
    170{
    171    fprintf(stderr, ": type %s effect %s",
    172            qxl_name(qxl_draw_type, draw->type),
    173            qxl_name(qxl_draw_effect, draw->effect));
    174    if (draw->bitmap_offset) {
    175        fprintf(stderr, ": bitmap %d",
    176                draw->bitmap_offset);
    177        qxl_log_rect(&draw->bitmap_area);
    178    }
    179    switch (draw->type) {
    180    case QXL_DRAW_COPY:
    181        return qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id);
    182    }
    183    return 0;
    184}
    185
    186static void qxl_log_cmd_surface(PCIQXLDevice *qxl, QXLSurfaceCmd *cmd)
    187{
    188    fprintf(stderr, ": %s id %d",
    189            qxl_name(qxl_surface_cmd, cmd->type),
    190            cmd->surface_id);
    191    if (cmd->type == QXL_SURFACE_CMD_CREATE) {
    192        fprintf(stderr, " size %dx%d stride %d format %s (count %u, max %u)",
    193                cmd->u.surface_create.width,
    194                cmd->u.surface_create.height,
    195                cmd->u.surface_create.stride,
    196                qxl_name(spice_surface_fmt, cmd->u.surface_create.format),
    197                qxl->guest_surfaces.count, qxl->guest_surfaces.max);
    198    }
    199    if (cmd->type == QXL_SURFACE_CMD_DESTROY) {
    200        fprintf(stderr, " (count %u)", qxl->guest_surfaces.count);
    201    }
    202}
    203
    204int qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id)
    205{
    206    QXLCursor *cursor;
    207
    208    fprintf(stderr, ": %s",
    209            qxl_name(qxl_cursor_cmd, cmd->type));
    210    switch (cmd->type) {
    211    case QXL_CURSOR_SET:
    212        fprintf(stderr, " +%d+%d visible %s, shape @ 0x%" PRIx64,
    213                cmd->u.set.position.x,
    214                cmd->u.set.position.y,
    215                cmd->u.set.visible ? "yes" : "no",
    216                cmd->u.set.shape);
    217        cursor = qxl_phys2virt(qxl, cmd->u.set.shape, group_id);
    218        if (!cursor) {
    219            return 1;
    220        }
    221        fprintf(stderr, " type %s size %dx%d hot-spot +%d+%d"
    222                " unique 0x%" PRIx64 " data-size %d",
    223                qxl_name(spice_cursor_type, cursor->header.type),
    224                cursor->header.width, cursor->header.height,
    225                cursor->header.hot_spot_x, cursor->header.hot_spot_y,
    226                cursor->header.unique, cursor->data_size);
    227        break;
    228    case QXL_CURSOR_MOVE:
    229        fprintf(stderr, " +%d+%d", cmd->u.position.x, cmd->u.position.y);
    230        break;
    231    }
    232    return 0;
    233}
    234
    235int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext)
    236{
    237    bool compat = ext->flags & QXL_COMMAND_FLAG_COMPAT;
    238    void *data;
    239    int ret;
    240
    241    if (!qxl->cmdlog) {
    242        return 0;
    243    }
    244    fprintf(stderr, "%" PRId64 " qxl-%d/%s:", qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
    245            qxl->id, ring);
    246    fprintf(stderr, " cmd @ 0x%" PRIx64 " %s%s", ext->cmd.data,
    247            qxl_name(qxl_type, ext->cmd.type),
    248            compat ? "(compat)" : "");
    249
    250    data = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
    251    if (!data) {
    252        return 1;
    253    }
    254    switch (ext->cmd.type) {
    255    case QXL_CMD_DRAW:
    256        if (!compat) {
    257            ret = qxl_log_cmd_draw(qxl, data, ext->group_id);
    258        } else {
    259            ret = qxl_log_cmd_draw_compat(qxl, data, ext->group_id);
    260        }
    261        if (ret) {
    262            return ret;
    263        }
    264        break;
    265    case QXL_CMD_SURFACE:
    266        qxl_log_cmd_surface(qxl, data);
    267        break;
    268    case QXL_CMD_CURSOR:
    269        qxl_log_cmd_cursor(qxl, data, ext->group_id);
    270        break;
    271    }
    272    fprintf(stderr, "\n");
    273    return 0;
    274}