Commit 93f874fe authored by Marc-André Lureau's avatar Marc-André Lureau Committed by Peter Maydell
Browse files

virtio-gpu: fix crashes upon warm reboot with vga mode

With vga=775 on the Linux command line a first boot of the VM running
Linux works fine. After a warm reboot it crashes during Linux boot.

Before that, valgrind points out bad memory write to console
surface. The VGA code is not aware that virtio-gpu got a message
surface scanout when the display is disabled. Let's reset VGA graphic
mode when it is the case, so that a new display surface is created
when doing further VGA operations.

https://bugs.launchpad.net/qemu/+bug/1784900/



Reported-by: default avatarStefan Berger <stefanb@linux.vnet.ibm.com>
Signed-off-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Reviewed-by: default avatarGerd Hoffmann <kraxel@redhat.com>
Tested-by: default avatarStefan Berger <stefanb@linux.vnet.ibm.com>
Message-id: 20180803153235.4134-1-marcandre.lureau@redhat.com
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parent 09b94ac0
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -421,6 +421,11 @@ static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id)
                                         scanout->height ?: 480,
                                         "Guest disabled display.");
    }

    if (g->disable_scanout) {
        g->disable_scanout(g, scanout_id);
    }

    dpy_gfx_replace_surface(scanout->con, ds);
    scanout->resource_id = 0;
    scanout->ds = NULL;
+11 −0
Original line number Diff line number Diff line
@@ -75,6 +75,16 @@ static void virtio_vga_gl_block(void *opaque, bool block)
    }
}

static void virtio_vga_disable_scanout(VirtIOGPU *g, int scanout_id)
{
    VirtIOVGA *vvga = container_of(g, VirtIOVGA, vdev);

    if (scanout_id == 0) {
        /* reset surface if needed */
        vvga->vga.graphic_mode = -1;
    }
}

static const GraphicHwOps virtio_vga_ops = {
    .invalidate = virtio_vga_invalidate_display,
    .gfx_update = virtio_vga_update_display,
@@ -156,6 +166,7 @@ static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
                                 vvga->vga_mrs, true);

    vga->con = g->scanout[0].con;
    g->disable_scanout = virtio_vga_disable_scanout;
    graphic_console_set_hwops(vga->con, &virtio_vga_ops, vvga);

    for (i = 0; i < g->conf.max_outputs; i++) {
+1 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ typedef struct VirtIOGPU {
        uint32_t bytes_3d;
    } stats;

    void (*disable_scanout)(struct VirtIOGPU *g, int scanout_id);
    Error *migration_blocker;
} VirtIOGPU;