vga: fixes for qxl and virtio-gpu
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEoDKM/7k6F6eZAf59TLbY7tPocTgFAmD6WZoACgkQTLbY7tPo cTjmORAAifkEHE4KUa2btyWzGGRu/2OKkF4kJwhYgA5GJdh1gbaKudeTq9jA/+PP QAGogwHV2iYJz3jIdljbQQZONBwF9milW9gYwd8j5J0UqB0NEVVY1txpo7ZKVEUI icMPZqrIY+ul0YNHnDXQXTBm5e+wiEGEoCOMOUGdqLiZ66zaMdwYicCbtLbOR5QV nF9acShrQWzHxCs8V1VNToo4syVFYYNxV/0/OyOJPdvIWekIp5YUkc5g5Fn9QOH5 rzSElqf3iK8KOciVf25w3bvZNcknkFFCq+wLBLkmk/d0tGvE+dF0YYo1w0GW27BN kWm+AvD0xKs4O+BGxD4vYrnNbrL7uGobZ9jsz2mHNbx5yiqPEYpF6zB7aSqWzMwn Zewdv2VpmkWGrOTGNU0BtYpP+0/jscO0Tk8TyqpTEAj6+NSBtOHd7VgkP0rQ+6t1 lbYmwbiUtZkoeauo0mggdrEKcZtNrJriOMXTSuv2vp9gYsns2unlG9HK20twmGVo 7+W935Im52s16mxYUf+kiiNbofn73U34oB0cud/W1d1bOzAj10UBXJbBbRsZ7a8+ Vkzx2OBRRPpyoOAYGq2xzRHIYtQswxhICYbLJ9m0w35Nm+Fwy9PxV1uYT9wcXQyG U5WavBPR+nUOE2+zPolArdU2D+3B/GnMoQZ54n07IXPMhv/iCf4= =HCps -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/vga-20210723-pull-request' into staging vga: fixes for qxl and virtio-gpu # gpg: Signature made Fri 23 Jul 2021 06:54:34 BST # gpg: using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full] # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/vga-20210723-pull-request: hw/display: fix virgl reset regression vl: add virtio-vga-gl to the default_list hw/display: fail early when multiple virgl devices are requested Revert "qxl: add migration blocker to avoid pre-save assert" qxl: remove assert in qxl_pre_save. hw/display/virtio-gpu: Fix memory leak (CID 1453811) Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
a146af86c8
@ -30,7 +30,6 @@
|
||||
#include "qemu/module.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "migration/blocker.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "trace.h"
|
||||
|
||||
@ -666,30 +665,6 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
|
||||
qxl->guest_primary.commands++;
|
||||
qxl_track_command(qxl, ext);
|
||||
qxl_log_command(qxl, "cmd", ext);
|
||||
{
|
||||
/*
|
||||
* Windows 8 drivers place qxl commands in the vram
|
||||
* (instead of the ram) bar. We can't live migrate such a
|
||||
* guest, so add a migration blocker in case we detect
|
||||
* this, to avoid triggering the assert in pre_save().
|
||||
*
|
||||
* https://cgit.freedesktop.org/spice/win32/qxl-wddm-dod/commit/?id=f6e099db39e7d0787f294d5fd0dce328b5210faa
|
||||
*/
|
||||
void *msg = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
|
||||
if (msg != NULL && (
|
||||
msg < (void *)qxl->vga.vram_ptr ||
|
||||
msg > ((void *)qxl->vga.vram_ptr + qxl->vga.vram_size))) {
|
||||
if (!qxl->migration_blocker) {
|
||||
Error *local_err = NULL;
|
||||
error_setg(&qxl->migration_blocker,
|
||||
"qxl: guest bug: command not in ram bar");
|
||||
migrate_add_blocker(qxl->migration_blocker, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
|
||||
return true;
|
||||
default:
|
||||
@ -1283,12 +1258,6 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
|
||||
qemu_spice_create_host_memslot(&d->ssd);
|
||||
qxl_soft_reset(d);
|
||||
|
||||
if (d->migration_blocker) {
|
||||
migrate_del_blocker(d->migration_blocker);
|
||||
error_free(d->migration_blocker);
|
||||
d->migration_blocker = NULL;
|
||||
}
|
||||
|
||||
if (startstop) {
|
||||
qemu_spice_display_start();
|
||||
}
|
||||
@ -2283,7 +2252,9 @@ static int qxl_pre_save(void *opaque)
|
||||
} else {
|
||||
d->last_release_offset = (uint8_t *)d->last_release - ram_start;
|
||||
}
|
||||
assert(d->last_release_offset < d->vga.vram_size);
|
||||
if (d->last_release_offset < d->vga.vram_size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -39,7 +39,6 @@ struct PCIQXLDevice {
|
||||
uint32_t cmdlog;
|
||||
|
||||
uint32_t guest_bug;
|
||||
Error *migration_blocker;
|
||||
|
||||
enum qxl_mode mode;
|
||||
uint32_t cmdflags;
|
||||
|
@ -51,12 +51,7 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
|
||||
static void virtio_gpu_gl_flushed(VirtIOGPUBase *b)
|
||||
{
|
||||
VirtIOGPU *g = VIRTIO_GPU(b);
|
||||
VirtIOGPUGL *gl = VIRTIO_GPU_GL(b);
|
||||
|
||||
if (gl->renderer_reset) {
|
||||
gl->renderer_reset = false;
|
||||
virtio_gpu_virgl_reset(g);
|
||||
}
|
||||
virtio_gpu_process_cmdq(g);
|
||||
}
|
||||
|
||||
@ -74,6 +69,10 @@ static void virtio_gpu_gl_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
|
||||
virtio_gpu_virgl_init(g);
|
||||
gl->renderer_inited = true;
|
||||
}
|
||||
if (gl->renderer_reset) {
|
||||
gl->renderer_reset = false;
|
||||
virtio_gpu_virgl_reset(g);
|
||||
}
|
||||
|
||||
cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
|
||||
while (cmd) {
|
||||
@ -95,12 +94,13 @@ static void virtio_gpu_gl_reset(VirtIODevice *vdev)
|
||||
|
||||
virtio_gpu_reset(vdev);
|
||||
|
||||
if (gl->renderer_inited) {
|
||||
if (g->parent_obj.renderer_blocked) {
|
||||
gl->renderer_reset = true;
|
||||
} else {
|
||||
virtio_gpu_virgl_reset(g);
|
||||
}
|
||||
/*
|
||||
* GL functions must be called with the associated GL context in main
|
||||
* thread, and when the renderer is unblocked.
|
||||
*/
|
||||
if (gl->renderer_inited && !gl->renderer_reset) {
|
||||
virtio_gpu_virgl_reset_scanout(g);
|
||||
gl->renderer_reset = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,6 +113,11 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, Error **errp)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!object_resolve_path_type("", TYPE_VIRTIO_GPU_GL, NULL)) {
|
||||
error_setg(errp, "at most one %s device is permitted", TYPE_VIRTIO_GPU_GL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!display_opengl) {
|
||||
error_setg(errp, "opengl is not available");
|
||||
return;
|
||||
|
@ -588,17 +588,21 @@ void virtio_gpu_virgl_fence_poll(VirtIOGPU *g)
|
||||
virtio_gpu_fence_poll(g);
|
||||
}
|
||||
|
||||
void virtio_gpu_virgl_reset(VirtIOGPU *g)
|
||||
void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g)
|
||||
{
|
||||
int i;
|
||||
|
||||
virgl_renderer_reset();
|
||||
for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
|
||||
dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL);
|
||||
dpy_gl_scanout_disable(g->parent_obj.scanout[i].con);
|
||||
}
|
||||
}
|
||||
|
||||
void virtio_gpu_virgl_reset(VirtIOGPU *g)
|
||||
{
|
||||
virgl_renderer_reset();
|
||||
}
|
||||
|
||||
int virtio_gpu_virgl_init(VirtIOGPU *g)
|
||||
{
|
||||
int ret;
|
||||
|
@ -340,8 +340,15 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU *g,
|
||||
return;
|
||||
}
|
||||
|
||||
res = virtio_gpu_find_resource(g, cblob.resource_id);
|
||||
if (res) {
|
||||
if (cblob.blob_mem != VIRTIO_GPU_BLOB_MEM_GUEST &&
|
||||
cblob.blob_flags != VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid memory type\n",
|
||||
__func__);
|
||||
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
|
||||
return;
|
||||
}
|
||||
|
||||
if (virtio_gpu_find_resource(g, cblob.resource_id)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
|
||||
__func__, cblob.resource_id);
|
||||
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
|
||||
@ -352,25 +359,12 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU *g,
|
||||
res->resource_id = cblob.resource_id;
|
||||
res->blob_size = cblob.size;
|
||||
|
||||
if (cblob.blob_mem != VIRTIO_GPU_BLOB_MEM_GUEST &&
|
||||
cblob.blob_flags != VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid memory type\n",
|
||||
__func__);
|
||||
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
|
||||
g_free(res);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res->iov) {
|
||||
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
||||
return;
|
||||
}
|
||||
|
||||
ret = virtio_gpu_create_mapping_iov(g, cblob.nr_entries, sizeof(cblob),
|
||||
cmd, &res->addrs, &res->iov,
|
||||
&res->iov_cnt);
|
||||
if (ret != 0) {
|
||||
if (ret != 0 || res->iov) {
|
||||
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
||||
g_free(res);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -279,6 +279,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
|
||||
void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
|
||||
struct virtio_gpu_ctrl_command *cmd);
|
||||
void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
|
||||
void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
|
||||
void virtio_gpu_virgl_reset(VirtIOGPU *g);
|
||||
int virtio_gpu_virgl_init(VirtIOGPU *g);
|
||||
int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
|
||||
|
@ -202,6 +202,7 @@ static struct {
|
||||
{ .driver = "virtio-vga", .flag = &default_vga },
|
||||
{ .driver = "ati-vga", .flag = &default_vga },
|
||||
{ .driver = "vhost-user-vga", .flag = &default_vga },
|
||||
{ .driver = "virtio-vga-gl", .flag = &default_vga },
|
||||
};
|
||||
|
||||
static QemuOptsList qemu_rtc_opts = {
|
||||
|
Loading…
Reference in New Issue
Block a user