Various fixes

Collect various graphics & chardev fixes, and some others.
 
 Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmqNeowACgkQ2ujhCXWW
 nOWcsg//VwpHLApYC+ovKfZJm+4m0NUydmsxsYnQXSNhkPEueXMFPu91qu6sLW+c
 T8eRDwCZaItM4te6nKQ46RiD7GOw5M7AB+D7F6H7za5L8+I7j2QGzTz4N1FQnFLL
 0t3FTjzgNri99/UFd1Tpvkh3r4tmLRN1gvGIslvfVtpXLPq0GlVmseDY+Tih4Vz9
 TZn0jAg1WoR4v4YrtkfWvk/Dl5nzM3CRTiqLYz1/jfUB4kUpo/VxU1pk1Ky3LglK
 osrn6pcWxsFD2VLNZwoIMVzrdLjA9w7cIPwLI3JkNop3MD0GtSkAIoT4nSGji8uI
 Ck3CeuQKwZzHeBb4RJBAjEnVXJSpIhgLD5uQ3B4oIGMvfH0FxUphXZ6I77kehs8V
 awJwlE5c1tsuHcdcj67rrrcW3rzMVdDVCyin+xLJw7TkfofV9P/WH88pGO19EdOY
 eyNuwZLHDmrw08KzGEHlzoPRwh01+ihnTB+/eTPJjDDsOgIIQLjjeD06a878XUkm
 bLFnQktMr0DKFwx1wqkKXAqKLAvoWDTcDhlN9a67Y2G1MsGvROmLOsl4EPFqyfK5
 +phEDzZvRD4dWm1vZhI1ZUfORfTXd67naBLAyvSvFZHEbiDtji6RplmSaP8MgA21
 dRWRkUxlfQp0cIgzq/5DgnA3I0buVwfGxz8oeoQDwe2yXPdJBEs=
 =2qCQ
 -----END PGP SIGNATURE-----

Merge tag 'fixes-pr-v1' of https://gitlab.com/marcandre.lureau/qemu into staging

Various fixes

Collect various graphics & chardev fixes, and some others.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmqNeowACgkQ2ujhCXWW
# nOWcsg//VwpHLApYC+ovKfZJm+4m0NUydmsxsYnQXSNhkPEueXMFPu91qu6sLW+c
# T8eRDwCZaItM4te6nKQ46RiD7GOw5M7AB+D7F6H7za5L8+I7j2QGzTz4N1FQnFLL
# 0t3FTjzgNri99/UFd1Tpvkh3r4tmLRN1gvGIslvfVtpXLPq0GlVmseDY+Tih4Vz9
# TZn0jAg1WoR4v4YrtkfWvk/Dl5nzM3CRTiqLYz1/jfUB4kUpo/VxU1pk1Ky3LglK
# osrn6pcWxsFD2VLNZwoIMVzrdLjA9w7cIPwLI3JkNop3MD0GtSkAIoT4nSGji8uI
# Ck3CeuQKwZzHeBb4RJBAjEnVXJSpIhgLD5uQ3B4oIGMvfH0FxUphXZ6I77kehs8V
# awJwlE5c1tsuHcdcj67rrrcW3rzMVdDVCyin+xLJw7TkfofV9P/WH88pGO19EdOY
# eyNuwZLHDmrw08KzGEHlzoPRwh01+ihnTB+/eTPJjDDsOgIIQLjjeD06a878XUkm
# bLFnQktMr0DKFwx1wqkKXAqKLAvoWDTcDhlN9a67Y2G1MsGvROmLOsl4EPFqyfK5
# +phEDzZvRD4dWm1vZhI1ZUfORfTXd67naBLAyvSvFZHEbiDtji6RplmSaP8MgA21
# dRWRkUxlfQp0cIgzq/5DgnA3I0buVwfGxz8oeoQDwe2yXPdJBEs=
# =2qCQ
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 25 Aug 2026 04:20:44 AM PDT
# gpg:                using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [unknown]
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* tag 'fixes-pr-v1' of https://gitlab.com/marcandre.lureau/qemu:
  hw/input/ps2: say why unknown keyboard commands draw a resend
  hw/input/ps2: answer unknown mouse commands with a resend
  hw/display/virtio-gpu: Validate resource per command
  hw/display/virtio-gpu: Check cursor data presence
  hw/display/virtio-gpu: Propagate udmabuf errors
  hw/display/virtio-gpu: Avoid mmap() for empty blob
  hw/display/virtio-gpu: Avoid creating empty udmabuf
  hw/display/vga: fix text-mode OOB write after a graphics surface switch
  chardev: Don't unregister yank upon async path connection failure
  tests/functional: fix pylint false positives for cv2 module
  ui/egl: fix qemu_egl_display type
  ui/egl: fix render node cleanup order
  tests: tag slow tests with 'slow' suite for easy filtering
  crypto: fix build against nettle >= 4
  virtio-gpu: use g_try_malloc to avoid guest-triggered abort
  hw/display/qxl: validate primary surface stride against width
  hw/core/machine: fix fdt memory leak
  migration/multifd: fix Error leak in multifd_recv_terminate_threads()
  hw/misc: fix trace-events

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2026-08-25 06:48:55 -07:00
commit fe11f459f6
25 changed files with 372 additions and 164 deletions

View file

@ -1128,11 +1128,6 @@ static void qemu_chr_socket_connected(QIOTask *task, void *opaque)
if (qio_task_propagate_error(task, &err)) {
tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
if (s->registered_yank) {
yank_unregister_function(CHARDEV_YANK_INSTANCE(chr->label),
char_socket_yank_iochannel,
QIO_CHANNEL(sioc));
}
check_report_connect_error(chr, err);
goto cleanup;
}

View file

@ -487,7 +487,7 @@ vg_create_mapping_iov(VuGpu *g,
struct virtio_gpu_ctrl_command *cmd,
struct iovec **iov)
{
struct virtio_gpu_mem_entry *ents;
g_autofree struct virtio_gpu_mem_entry *ents = NULL;
size_t esize, s;
int i;
@ -498,17 +498,22 @@ vg_create_mapping_iov(VuGpu *g,
}
esize = sizeof(*ents) * ab->nr_entries;
ents = g_malloc(esize);
ents = g_try_malloc(esize);
if (!ents && esize) {
return -1;
}
s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
sizeof(*ab), ents, esize);
if (s != esize) {
g_critical("%s: command data size incorrect %zu vs %zu",
__func__, s, esize);
g_free(ents);
return -1;
}
*iov = g_new0(struct iovec, ab->nr_entries);
*iov = g_try_new0(struct iovec, ab->nr_entries);
if (!*iov && ab->nr_entries) {
return -1;
}
for (i = 0; i < ab->nr_entries; i++) {
uint64_t len = ents[i].length;
(*iov)[i].iov_len = ents[i].length;
@ -517,12 +522,10 @@ vg_create_mapping_iov(VuGpu *g,
g_critical("%s: resource %d element %d",
__func__, ab->resource_id, i);
g_free(*iov);
g_free(ents);
*iov = NULL;
return -1;
}
}
g_free(ents);
return 0;
}
@ -828,8 +831,14 @@ vg_resource_flush(VuGpu *g,
PIXMAN_FORMAT_BPP(pixman_image_get_format(res->image)) / 8;
size_t size = width * height * bpp;
void *p = g_malloc(VHOST_USER_GPU_HDR_SIZE +
sizeof(VhostUserGpuUpdate) + size);
void *p = g_try_malloc(VHOST_USER_GPU_HDR_SIZE +
sizeof(VhostUserGpuUpdate) + size);
if (!p) {
pixman_region_fini(&region);
pixman_region_fini(&finalregion);
cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
break;
}
VhostUserGpuMsg *msg = p;
msg->request = VHOST_USER_GPU_UPDATE;
msg->size = sizeof(VhostUserGpuUpdate) + size;

View file

@ -209,7 +209,11 @@ virgl_cmd_submit_3d(VuGpu *g,
return;
}
buf = g_malloc(cs.size);
buf = g_try_malloc(cs.size);
if (!buf && cs.size) {
cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
return;
}
s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
sizeof(cs), buf, cs.size);
if (s != cs.size) {

View file

@ -13,7 +13,10 @@
static bool
mem_alloc_bo(struct vugbm_buffer *buf)
{
buf->mmap = g_malloc((uint64_t)buf->width * buf->height * 4);
buf->mmap = g_try_malloc((uint64_t)buf->width * buf->height * 4);
if (!buf->mmap && buf->width && buf->height) {
return false;
}
buf->stride = buf->width * 4;
return true;
}

View file

@ -24,7 +24,8 @@
#include "crypto/hash.h"
#include "hashpriv.h"
#include <nettle/md5.h>
#include <nettle/sha.h>
#include <nettle/sha1.h>
#include <nettle/sha2.h>
#include <nettle/ripemd160.h>
#ifdef CONFIG_CRYPTO_SM3
#include <nettle/sm3.h>

View file

@ -1314,6 +1314,7 @@ static void machine_finalize(Object *obj)
g_free(ms->nvdimms_state);
g_free(ms->numa_state);
g_free(ms->audiodev);
g_free(ms->fdt);
}
bool machine_usb(MachineState *machine)

View file

@ -27,6 +27,7 @@
static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
{
DisplaySurface *surface = qemu_console_surface(qxl->vga.con);
int dst_stride = surface_stride(surface);
uint8_t *dst = surface_data(surface);
uint8_t *src;
int len, i;
@ -45,14 +46,14 @@ static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
} else {
src += rect->top * qxl->guest_primary.abs_stride;
}
dst += rect->top * qxl->guest_primary.abs_stride;
dst += rect->top * dst_stride;
src += rect->left * qxl->guest_primary.bytes_pp;
dst += rect->left * qxl->guest_primary.bytes_pp;
len = (rect->right - rect->left) * qxl->guest_primary.bytes_pp;
for (i = rect->top; i < rect->bottom; i++) {
memcpy(dst, src, len);
dst += qxl->guest_primary.abs_stride;
dst += dst_stride;
src += qxl->guest_primary.qxl_stride;
}
}
@ -61,30 +62,13 @@ void qxl_render_resize(PCIQXLDevice *qxl)
{
QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
qxl->guest_primary.qxl_stride = sc->stride;
qxl->guest_primary.abs_stride = abs(sc->stride);
qxl->guest_primary.qxl_stride = le32_to_cpu(sc->stride);
qxl->guest_primary.abs_stride = abs(qxl->guest_primary.qxl_stride);
qxl->guest_primary.resized++;
switch (sc->format) {
case SPICE_SURFACE_FMT_16_555:
qxl->guest_primary.bytes_pp = 2;
qxl->guest_primary.bits_pp = 15;
break;
case SPICE_SURFACE_FMT_16_565:
qxl->guest_primary.bytes_pp = 2;
qxl->guest_primary.bits_pp = 16;
break;
case SPICE_SURFACE_FMT_32_xRGB:
case SPICE_SURFACE_FMT_32_ARGB:
qxl->guest_primary.bytes_pp = 4;
qxl->guest_primary.bits_pp = 32;
break;
default:
fprintf(stderr, "%s: unhandled format: %x\n", __func__,
qxl->guest_primary.surface.format);
qxl->guest_primary.bytes_pp = 4;
qxl->guest_primary.bits_pp = 32;
break;
}
/* fallback to default bpp if format is unknown */
qxl_format_bpp(qxl, le32_to_cpu(sc->format),
&qxl->guest_primary.bytes_pp,
&qxl->guest_primary.bits_pp);
}
static void qxl_set_rect_to_surface(PCIQXLDevice *qxl, QXLRect *area)
@ -101,15 +85,45 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
DisplaySurface *surface;
int width = qxl->guest_head0_width ?: qxl->guest_primary.surface.width;
int height = qxl->guest_head0_height ?: qxl->guest_primary.surface.height;
uint64_t map_height;
int i;
if (width <= 0 || height <= 0) {
goto end;
}
if (qxl->guest_primary.bytes_pp > 0) {
int max_width = qxl->guest_primary.abs_stride
/ qxl->guest_primary.bytes_pp;
width = MIN(width, max_width);
}
if (qxl->guest_primary.qxl_stride < 0) {
/* qxl_blit() uses the primary height to find the first scanline. */
height = MIN(height, (int)qxl->guest_primary.surface.height);
}
if (qxl->guest_primary.abs_stride > 0) {
int max_height = qxl->vgamem_size / qxl->guest_primary.abs_stride;
height = MIN(height, max_height);
}
/*
* height limits the visible update, while map_height is the guest memory
* span validated by qxl_phys2virt(). With a negative stride qxl_blit()
* addresses scanlines from the declared primary height, so a shorter
* monitor still requires validating the full primary surface.
*/
map_height = qxl->guest_primary.qxl_stride < 0 ?
qxl->guest_primary.surface.height : height;
if (qxl->guest_primary.resized) {
qxl->guest_primary.resized = 0;
qxl->guest_primary.data = qxl_phys2virt(qxl,
qxl->guest_primary.surface.mem,
MEMSLOT_GROUP_GUEST,
qxl->guest_primary.abs_stride
* height);
* map_height);
if (!qxl->guest_primary.data) {
goto end;
}

View file

@ -1489,6 +1489,47 @@ static void qxl_create_guest_primary_complete(PCIQXLDevice *qxl)
qxl_render_resize(qxl);
}
/*
* Convert a SpiceSurfaceFormat to bytes per pixel and bits per pixel.
*
* Only valid for surface suitable for rendering.
*/
bool qxl_format_bpp(PCIQXLDevice *qxl, SpiceSurfaceFmt format,
uint32_t *bytes_pp, uint32_t *bits_pp)
{
uint32_t bypp = 4;
uint32_t bipp = 32;
bool ret = true;
switch (format) {
case SPICE_SURFACE_FMT_16_555:
bypp = 2;
bipp = 15;
break;
case SPICE_SURFACE_FMT_16_565:
bypp = 2;
bipp = 16;
break;
case SPICE_SURFACE_FMT_32_xRGB:
case SPICE_SURFACE_FMT_32_ARGB:
bypp = 4;
bipp = 32;
break;
default:
ret = false;
qxl_set_guest_bug(qxl, "%s: unhandled format: %x", __func__, format);
}
if (bytes_pp != NULL) {
*bytes_pp = bypp;
}
if (bits_pp != NULL) {
*bits_pp = bipp;
}
return ret;
}
static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
qxl_async_io async)
{
@ -1496,6 +1537,7 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
uint32_t requested_height = le32_to_cpu(sc->height);
int requested_stride = le32_to_cpu(sc->stride);
uint32_t bytes_pp;
if (requested_stride == INT32_MIN ||
abs(requested_stride) * (uint64_t)requested_height
@ -1532,6 +1574,23 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
return;
}
if (!qxl_format_bpp(qxl, surface.format, &bytes_pp, NULL)) {
return;
}
if (surface.width == 0 || surface.height == 0) {
qxl_set_guest_bug(qxl, "%s: zero dimension %ux%u",
__func__, surface.width, surface.height);
return;
}
if ((uint64_t)surface.width * bytes_pp > abs(surface.stride)) {
qxl_set_guest_bug(qxl, "%s: stride too small for width:"
" stride %d width %u bpp %u",
__func__, surface.stride, surface.width, bytes_pp);
return;
}
surface.mouse_mode = true;
surface.group_id = MEMSLOT_GROUP_GUEST;
if (loadvm) {

View file

@ -181,6 +181,8 @@ void qxl_spice_oom(PCIQXLDevice *qxl);
void qxl_spice_reset_memslots(PCIQXLDevice *qxl);
void qxl_spice_reset_image_cache(PCIQXLDevice *qxl);
void qxl_spice_reset_cursor(PCIQXLDevice *qxl);
bool qxl_format_bpp(PCIQXLDevice *qxl, SpiceSurfaceFmt format,
uint32_t *bytes_pp, uint32_t *bits_pp);
/* qxl-logger.c */
int qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id);

View file

@ -1241,7 +1241,10 @@ static void vga_draw_text(VGACommonState *s, int full_update)
return;
}
if (width != s->last_width || height != s->last_height ||
if (surface == NULL ||
surface_width(surface) != width * cw ||
surface_height(surface) != height * cheight ||
width != s->last_text_width || height != s->last_text_height ||
cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
s->last_scr_width = width * cw;
s->last_scr_height = height * cheight;
@ -1249,8 +1252,8 @@ static void vga_draw_text(VGACommonState *s, int full_update)
surface = qemu_console_surface(s->con);
qemu_console_text_resize(s->con, width, height);
s->last_depth = 0;
s->last_width = width;
s->last_height = height;
s->last_text_width = width;
s->last_text_height = height;
s->last_ch = cheight;
s->last_cw = cw;
full_update = 1;
@ -1845,6 +1848,8 @@ static void vga_invalidate_display(void *opaque)
s->last_width = -1;
s->last_height = -1;
s->last_text_width = -1;
s->last_text_height = -1;
}
void vga_common_reset(VGACommonState *s)
@ -1887,6 +1892,8 @@ void vga_common_reset(VGACommonState *s)
s->last_ch = 0;
s->last_width = 0;
s->last_height = 0;
s->last_text_width = 0;
s->last_text_height = 0;
s->last_scr_width = 0;
s->last_scr_height = 0;
s->cursor_start = 0;
@ -1938,8 +1945,8 @@ static void vga_update_text(void *opaque, uint32_t *chardata)
s->graphic_mode = graphic_mode;
full_update = 1;
}
if (s->last_width == -1) {
s->last_width = 0;
if (s->last_text_width == -1) {
s->last_text_width = 0;
full_update = 1;
}
@ -1978,15 +1985,15 @@ static void vga_update_text(void *opaque, uint32_t *chardata)
break;
}
if (width != s->last_width || height != s->last_height ||
if (width != s->last_text_width || height != s->last_text_height ||
cw != s->last_cw || cheight != s->last_ch) {
s->last_scr_width = width * cw;
s->last_scr_height = height * cheight;
qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
qemu_console_text_resize(s->con, width, height);
s->last_depth = 0;
s->last_width = width;
s->last_height = height;
s->last_text_width = width;
s->last_text_height = height;
s->last_ch = cheight;
s->last_cw = cw;
full_update = 1;
@ -2071,22 +2078,22 @@ static void vga_update_text(void *opaque, uint32_t *chardata)
}
/* Display a message */
s->last_width = 60;
s->last_height = height = 3;
s->last_text_width = 60;
s->last_text_height = height = 3;
qemu_console_text_set_cursor(s->con, -1, -1);
qemu_console_text_resize(s->con, s->last_width, height);
qemu_console_text_resize(s->con, s->last_text_width, height);
for (dst = chardata, i = 0; i < s->last_width * height; i ++)
for (dst = chardata, i = 0; i < s->last_text_width * height; i ++)
*dst++ = ' ';
size = strlen(msg_buffer);
width = (s->last_width - size) / 2;
dst = chardata + s->last_width + width;
width = (s->last_text_width - size) / 2;
dst = chardata + s->last_text_width + width;
for (i = 0; i < size; i ++)
*dst++ = ATTR2CHTYPE(msg_buffer[i], QEMU_COLOR_BLUE,
QEMU_COLOR_BLACK, 1);
qemu_console_text_update(s->con, 0, 0, s->last_width, height);
qemu_console_text_update(s->con, 0, 0, s->last_text_width, height);
}
static uint64_t vga_mem_read(void *opaque, hwaddr addr,

View file

@ -122,7 +122,8 @@ typedef struct VGACommonState {
uint32_t plane_updated;
uint32_t last_line_offset;
uint8_t last_cw, last_ch;
uint32_t last_width, last_height; /* in chars or pixels */
uint32_t last_width, last_height; /* in pixels (graphics renderer) */
uint32_t last_text_width, last_text_height; /* in chars (text renderer) */
uint32_t last_scr_width, last_scr_height; /* in pixels */
uint32_t last_depth; /* in bits */
bool last_byteswap;

View file

@ -366,10 +366,20 @@ rutabaga_cmd_submit_3d(VirtIOGPU *g,
return;
}
buf = g_new0(uint8_t, cs.size);
buf = g_try_new0(uint8_t, cs.size);
if (!buf && cs.size) {
cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
return;
}
s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
sizeof(cs), buf, cs.size);
CHECK(s == cs.size, cmd);
if (s != cs.size) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: size mismatch (%zu/%u)\n",
__func__, s, cs.size);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
return;
}
rutabaga_cmd.ctx_id = cs.hdr.ctx_id;
rutabaga_cmd.cmd = buf;

View file

@ -7,9 +7,10 @@ bool virtio_gpu_have_udmabuf(void)
return false;
}
void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
{
/* nothing (stub) */
return false;
}
void virtio_gpu_fini_udmabuf(VirtIOGPU *g, struct virtio_gpu_simple_resource *res)

View file

@ -39,8 +39,11 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
return;
}
list = g_malloc0(sizeof(struct udmabuf_create_list) +
sizeof(struct udmabuf_create_item) * res->iov_cnt);
list = g_try_malloc0(sizeof(struct udmabuf_create_list) +
sizeof(struct udmabuf_create_item) * res->iov_cnt);
if (!list) {
return;
}
for (i = 0; i < res->iov_cnt; i++) {
rcu_read_lock();
@ -128,7 +131,7 @@ bool virtio_gpu_have_udmabuf(void)
return memfd_backend;
}
void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
{
void *pdata = NULL;
@ -136,20 +139,22 @@ void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
if (res->iov_cnt == 1 &&
res->iov[0].iov_len < 4096) {
pdata = res->iov[0].iov_base;
} else {
} else if (res->blob_size) {
virtio_gpu_create_udmabuf(res);
if (res->dmabuf_fd < 0) {
return;
return false;
}
virtio_gpu_remap_udmabuf(res);
if (!res->remapped) {
virtio_gpu_destroy_udmabuf(res);
return;
return false;
}
pdata = res->remapped;
}
res->blob = pdata;
return true;
}
static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf)

View file

@ -620,7 +620,11 @@ static void virgl_cmd_submit_3d(VirtIOGPU *g,
return;
}
buf = g_malloc(cs.size);
buf = g_try_malloc(cs.size);
if (!buf && cs.size) {
cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
return;
}
s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
sizeof(cs), buf, cs.size);
if (s != cs.size) {

View file

@ -37,7 +37,6 @@
static struct virtio_gpu_simple_resource *
virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
bool require_backing,
const char *caller, uint32_t *error);
static void virtio_gpu_reset_bh(void *opaque);
@ -50,8 +49,7 @@ void virtio_gpu_update_cursor_data(VirtIOGPU *g,
uint32_t pixels;
void *data;
res = virtio_gpu_find_check_resource(g, resource_id, false,
__func__, NULL);
res = virtio_gpu_find_check_resource(g, resource_id, __func__, NULL);
if (!res) {
return;
}
@ -63,8 +61,8 @@ void virtio_gpu_update_cursor_data(VirtIOGPU *g,
}
data = pixman_image_get_data(res->image);
} else {
if (res->blob_size < (s->current_cursor->width *
s->current_cursor->height * 4)) {
if (!res->iov || res->blob_size < (s->current_cursor->width *
s->current_cursor->height * 4)) {
return;
}
data = res->blob;
@ -128,7 +126,6 @@ virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id)
static struct virtio_gpu_simple_resource *
virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
bool require_backing,
const char *caller, uint32_t *error)
{
struct virtio_gpu_simple_resource *res;
@ -143,17 +140,6 @@ virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
return NULL;
}
if (require_backing) {
if (!res->iov || (!res->image && !res->blob)) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: no backing storage %d\n",
caller, resource_id);
if (error) {
*error = VIRTIO_GPU_RESP_ERR_UNSPEC;
}
return NULL;
}
}
return res;
}
@ -363,27 +349,34 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU *g,
res->resource_id = cblob.resource_id;
res->blob_size = cblob.size;
ret = virtio_gpu_create_mapping_iov(g, cblob.nr_entries, sizeof(cblob),
cmd, &res->addrs, &res->iov,
&res->iov_cnt);
if (ret < 0) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
g_free(res);
return;
if (cblob.nr_entries) {
ret = virtio_gpu_create_mapping_iov(g, cblob.nr_entries, sizeof(cblob),
cmd, &res->addrs, &res->iov,
&res->iov_cnt);
if (ret < 0) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
g_free(res);
return;
}
if (iov_size(res->iov, res->iov_cnt) < res->blob_size) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: backing storage smaller than blob size\n",
__func__);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
virtio_gpu_cleanup_mapping(g, res);
g_free(res);
return;
}
if (!virtio_gpu_init_udmabuf(res)) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
virtio_gpu_cleanup_mapping(g, res);
g_free(res);
return;
}
}
if (res->iov_cnt > 0 &&
iov_size(res->iov, res->iov_cnt) < res->blob_size) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: backing storage smaller than blob size\n",
__func__);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
virtio_gpu_cleanup_mapping(g, res);
g_free(res);
return;
}
virtio_gpu_init_udmabuf(res);
QTAILQ_INSERT_HEAD(&g->reslist, res, next);
}
@ -467,9 +460,24 @@ static void virtio_gpu_transfer_to_host_2d(VirtIOGPU *g,
virtio_gpu_t2d_bswap(&t2d);
trace_virtio_gpu_cmd_res_xfer_toh_2d(t2d.resource_id);
res = virtio_gpu_find_check_resource(g, t2d.resource_id, true,
res = virtio_gpu_find_check_resource(g, t2d.resource_id,
__func__, &cmd->error);
if (!res || res->blob) {
if (!res) {
return;
}
if (!res->image) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: resource %d is a blob\n",
__func__, t2d.resource_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
if (!res->iov) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: resource %d has no backing storage\n",
__func__, t2d.resource_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
@ -526,7 +534,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
trace_virtio_gpu_cmd_res_flush(rf.resource_id,
rf.r.width, rf.r.height, rf.r.x, rf.r.y);
res = virtio_gpu_find_check_resource(g, rf.resource_id, false,
res = virtio_gpu_find_check_resource(g, rf.resource_id,
__func__, &cmd->error);
if (!res) {
return;
@ -764,12 +772,19 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
return;
}
res = virtio_gpu_find_check_resource(g, ss.resource_id, true,
res = virtio_gpu_find_check_resource(g, ss.resource_id,
__func__, &cmd->error);
if (!res) {
return;
}
if (!res->image) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: resource %d is a blob\n",
__func__, ss.resource_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
fb.format = pixman_image_get_format(res->image);
bytes_pp = virtio_gpu_format_bytes_pp(fb.format);
fb.width = pixman_image_get_width(res->image);
@ -859,12 +874,28 @@ static void virtio_gpu_set_scanout_blob(VirtIOGPU *g,
return;
}
res = virtio_gpu_find_check_resource(g, ss.resource_id, true,
res = virtio_gpu_find_check_resource(g, ss.resource_id,
__func__, &cmd->error);
if (!res) {
return;
}
if (res->image) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: resource %d is not a blob\n",
__func__, ss.resource_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
if (!res->iov) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: resource %d has no backing storage\n",
__func__, ss.resource_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
if (!virtio_gpu_scanout_blob_to_fb(&fb, &ss, res->blob_size)) {
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
return;
@ -892,7 +923,10 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
}
esize = sizeof(*ents) * nr_entries;
ents = g_malloc(esize);
ents = g_try_malloc(esize);
if (!ents && esize) {
return -1;
}
s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
offset, ents, esize);
if (s != esize) {
@ -913,6 +947,7 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
hwaddr len;
void *map;
/* TODO: a common DMA map SG helper */
do {
len = l;
map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, &len,
@ -921,20 +956,27 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
if (!map) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
" element %d\n", __func__, e);
virtio_gpu_cleanup_mapping_iov(g, *iov, v);
g_free(ents);
*iov = NULL;
if (addr) {
g_free(*addr);
*addr = NULL;
}
return -1;
goto err;
}
if (!(v % 16)) {
*iov = g_renew(struct iovec, *iov, v + 16);
struct iovec *new_iov;
new_iov = g_try_renew(struct iovec, *iov, v + 16);
if (!new_iov) {
dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, map, len,
DMA_DIRECTION_TO_DEVICE, len);
goto err;
}
*iov = new_iov;
if (addr) {
*addr = g_renew(uint64_t, *addr, v + 16);
uint64_t *new_addr;
new_addr = g_try_renew(uint64_t, *addr, v + 16);
if (!new_addr) {
dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, map, len,
DMA_DIRECTION_TO_DEVICE, len);
goto err;
}
*addr = new_addr;
}
}
(*iov)[v].iov_base = map;
@ -952,6 +994,15 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
g_free(ents);
return 0;
err:
virtio_gpu_cleanup_mapping_iov(g, *iov, v);
*iov = NULL;
if (addr) {
g_clear_pointer(addr, g_free);
}
g_free(ents);
return -1;
}
void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g,
@ -1023,8 +1074,9 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
return;
}
if (!res->image) {
virtio_gpu_init_udmabuf(res);
if (!res->image && !virtio_gpu_init_udmabuf(res)) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
virtio_gpu_cleanup_mapping(g, res);
}
}
@ -1039,7 +1091,7 @@ virtio_gpu_resource_detach_backing(VirtIOGPU *g,
virtio_gpu_bswap_32(&detach, sizeof(detach));
trace_virtio_gpu_cmd_res_back_detach(detach.resource_id);
res = virtio_gpu_find_check_resource(g, detach.resource_id, true,
res = virtio_gpu_find_check_resource(g, detach.resource_id,
__func__, &cmd->error);
if (!res) {
return;
@ -1369,8 +1421,6 @@ static bool virtio_gpu_load_restore_mapping(VirtIOGPU *g,
}
}
QTAILQ_INSERT_HEAD(&g->reslist, res, next);
g->hostmem += res->hostmem;
return true;
}
@ -1449,6 +1499,8 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
return -EINVAL;
}
QTAILQ_INSERT_HEAD(&g->reslist, res, next);
g->hostmem += hostmem;
resource_id = qemu_get_be32(f);
}
@ -1508,36 +1560,42 @@ static int virtio_gpu_blob_load(QEMUFile *f, void *opaque, size_t size,
res->blob_size = qemu_get_be32(f);
res->iov_cnt = qemu_get_be32(f);
res->addrs = g_try_new(uint64_t, res->iov_cnt);
res->iov = g_try_new(struct iovec, res->iov_cnt);
if (res->iov_cnt && (!res->addrs || !res->iov)) {
g_free(res->addrs);
g_free(res->iov);
g_free(res);
return -EINVAL;
if (res->iov_cnt) {
res->addrs = g_try_new(uint64_t, res->iov_cnt);
res->iov = g_try_new(struct iovec, res->iov_cnt);
if (!res->addrs || !res->iov) {
g_free(res->addrs);
g_free(res->iov);
g_free(res);
return -EINVAL;
}
/* read data */
for (i = 0; i < res->iov_cnt; i++) {
res->addrs[i] = qemu_get_be64(f);
res->iov[i].iov_len = qemu_get_be32(f);
}
if (iov_size(res->iov, res->iov_cnt) < res->blob_size) {
g_free(res->addrs);
g_free(res->iov);
g_free(res);
return -EINVAL;
}
if (!virtio_gpu_load_restore_mapping(g, res)) {
g_free(res);
return -EINVAL;
}
if (!virtio_gpu_init_udmabuf(res)) {
virtio_gpu_cleanup_mapping(g, res);
g_free(res);
return -EINVAL;
}
}
/* read data */
for (i = 0; i < res->iov_cnt; i++) {
res->addrs[i] = qemu_get_be64(f);
res->iov[i].iov_len = qemu_get_be32(f);
}
if (res->iov_cnt > 0 &&
iov_size(res->iov, res->iov_cnt) < res->blob_size) {
g_free(res->addrs);
g_free(res->iov);
g_free(res);
return -EINVAL;
}
if (!virtio_gpu_load_restore_mapping(g, res)) {
g_free(res);
return -EINVAL;
}
virtio_gpu_init_udmabuf(res);
QTAILQ_INSERT_HEAD(&g->reslist, res, next);
resource_id = qemu_get_be32(f);
}

View file

@ -73,6 +73,7 @@
#define AUX_SET_DEFAULT 0xF6
#define AUX_RESET 0xFF /* Reset aux device */
#define AUX_ACK 0xFA /* Command byte ACK. */
#define AUX_RESEND 0xFE /* Command NACK, send the cmd again */
#define MOUSE_STATUS_REMOTE 0x40
#define MOUSE_STATUS_ENABLED 0x20
@ -646,6 +647,10 @@ void ps2_write_keyboard(PS2KbdState *s, int val)
ps2_cqueue_1(ps2, KBD_REPLY_ACK);
break;
default:
/*
* A PS/2 device answers every command it is given; an unknown
* one draws a resend.
*/
ps2_cqueue_1(ps2, KBD_REPLY_RESEND);
break;
}
@ -955,6 +960,11 @@ void ps2_write_mouse(PS2MouseState *s, int val)
s->mouse_type);
break;
default:
/*
* A PS/2 device answers every command it is given; an unknown
* one draws a resend.
*/
ps2_queue(ps2, AUX_RESEND);
break;
}
break;

View file

@ -446,3 +446,9 @@ iommu_testdev_dma_armed(bool armed) "armed=%d"
# k230_decomp_gzip.c
k230_decomp_gzip_read(uint64_t offset, unsigned int size, uint64_t value) "K230 DECOMP GZIP read: [0x%"PRIx64"] size %u -> 0x%"PRIx64
k230_decomp_gzip_write(uint64_t offset, unsigned int size, uint64_t value) "K230 DECOMP GZIP write: [0x%"PRIx64"] size %u <- 0x%"PRIx64
# vmlaunchupdate.c
launch_update_write(void) ""
vmlaunch_reset_enter(void) ""
vm_launchupdate_finalize(void) ""
restore_host_x86_igvm(void) ""

View file

@ -388,7 +388,7 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
/* virtio-gpu-udmabuf.c */
bool virtio_gpu_have_udmabuf(void);
void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res);
bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res);
void virtio_gpu_fini_udmabuf(VirtIOGPU *g,
struct virtio_gpu_simple_resource *res);
int virtio_gpu_update_dmabuf(VirtIOGPU *g,

View file

@ -9,7 +9,7 @@
#include "ui/console.h"
#include "ui/shader.h"
extern EGLDisplay *qemu_egl_display;
extern EGLDisplay qemu_egl_display;
extern EGLConfig qemu_egl_config;
extern DisplayGLMode qemu_egl_mode;
extern bool qemu_egl_angle_d3d;

View file

@ -1056,6 +1056,7 @@ static void multifd_recv_terminate_threads(Error *err)
trace_multifd_recv_terminate_threads(err != NULL);
if (qatomic_xchg(&multifd_recv_state->exiting, 1)) {
error_free(err);
return;
}

View file

@ -79,6 +79,12 @@ disable=bad-inline-option,
useless-suppression,
[TYPECHECK]
# cv2 is a C extension module whose members are not visible to pylint
generated-members=cv2.*
[SIMILARITIES]
# Minimum lines number of a similarity.

View file

@ -510,6 +510,7 @@ foreach dir : target_dirs
protocol: 'tap',
timeout: slow_qtests.get(test, 60),
priority: slow_qtests.get(test, 60),
suite: ['qtest', 'qtest-' + target_base])
suite: ['qtest', 'qtest-' + target_base] +
(slow_qtests.has_key(test) ? ['slow'] : []))
endforeach
endforeach

View file

@ -184,6 +184,12 @@ slow_tests = {
'test-crypto-tlscredsx509': 90,
'test-crypto-tlssession': 90,
'test-replication': 60,
'rcutorture': 30,
'test-rcu-list': 30,
'test-rcu-simpleq': 30,
'test-rcu-tailq': 30,
'test-rcu-slist': 30,
'test-thread-pool': 30,
}
foreach test_name, extra: tests
@ -205,5 +211,6 @@ foreach test_name, extra: tests
protocol: 'tap',
timeout: slow_tests.get(test_name, 30),
priority: slow_tests.get(test_name, 30),
suite: ['unit'])
suite: ['unit'] +
(slow_tests.has_key(test_name) ? ['slow'] : []))
endforeach

View file

@ -25,7 +25,7 @@
#include "trace.h"
#include "standard-headers/drm/drm_fourcc.h"
EGLDisplay *qemu_egl_display;
EGLDisplay qemu_egl_display;
EGLConfig qemu_egl_config;
DisplayGLMode qemu_egl_mode;
bool qemu_egl_angle_d3d;
@ -736,19 +736,22 @@ bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp)
void egl_cleanup(void)
{
if (qemu_egl_display) {
eglReleaseThread();
}
if (qemu_egl_rn_ctx) {
eglDestroyContext(qemu_egl_display, qemu_egl_rn_ctx);
qemu_egl_rn_ctx = NULL;
}
if (qemu_egl_display) {
eglTerminate(qemu_egl_display);
qemu_egl_display = NULL;
}
#ifdef CONFIG_GBM
g_clear_pointer(&qemu_egl_rn_gbm_dev, gbm_device_destroy);
g_clear_fd(&qemu_egl_rn_fd, NULL);
#endif
if (qemu_egl_display) {
eglReleaseThread();
eglTerminate(qemu_egl_display);
qemu_egl_display = NULL;
}
}