* [PULL 1/5] ui/vnc: Respect bound console
2024-03-12 14:02 [PULL 0/5] UI patches marcandre.lureau
@ 2024-03-12 14:02 ` marcandre.lureau
2024-03-12 14:02 ` [PULL 2/5] ui/dbus: factor out sending a scanout marcandre.lureau
` (4 subsequent siblings)
5 siblings, 0 replies; 19+ messages in thread
From: marcandre.lureau @ 2024-03-12 14:02 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Marc-André Lureau, Gerd Hoffmann,
Michael S. Tsirkin, Akihiko Odaki
From: Akihiko Odaki <akihiko.odaki@daynix.com>
ui/vnc may have a bound console so pass it to qemu_console_is_graphic()
and qemu_text_console_put_keysym().
Fixes: 1d0d59fe2919 ("vnc: allow binding servers to qemu consoles")
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20231211-vnc-v1-1-a3551d284809@daynix.com>
---
ui/vnc.c | 59 ++++++++++++++++++++++++++++----------------------------
1 file changed, 30 insertions(+), 29 deletions(-)
diff --git a/ui/vnc.c b/ui/vnc.c
index af20d24534..fc12b343e2 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1931,7 +1931,8 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
}
qkbd_state_key_event(vs->vd->kbd, qcode, down);
- if (!qemu_console_is_graphic(NULL)) {
+ if (!qemu_console_is_graphic(vs->vd->dcl.con)) {
+ QemuTextConsole *con = QEMU_TEXT_CONSOLE(vs->vd->dcl.con);
bool numlock = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK);
bool control = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL);
/* QEMU console emulation */
@@ -1945,88 +1946,88 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
case 0xb8: /* Right ALT */
break;
case 0xc8:
- qemu_text_console_put_keysym(NULL, QEMU_KEY_UP);
+ qemu_text_console_put_keysym(con, QEMU_KEY_UP);
break;
case 0xd0:
- qemu_text_console_put_keysym(NULL, QEMU_KEY_DOWN);
+ qemu_text_console_put_keysym(con, QEMU_KEY_DOWN);
break;
case 0xcb:
- qemu_text_console_put_keysym(NULL, QEMU_KEY_LEFT);
+ qemu_text_console_put_keysym(con, QEMU_KEY_LEFT);
break;
case 0xcd:
- qemu_text_console_put_keysym(NULL, QEMU_KEY_RIGHT);
+ qemu_text_console_put_keysym(con, QEMU_KEY_RIGHT);
break;
case 0xd3:
- qemu_text_console_put_keysym(NULL, QEMU_KEY_DELETE);
+ qemu_text_console_put_keysym(con, QEMU_KEY_DELETE);
break;
case 0xc7:
- qemu_text_console_put_keysym(NULL, QEMU_KEY_HOME);
+ qemu_text_console_put_keysym(con, QEMU_KEY_HOME);
break;
case 0xcf:
- qemu_text_console_put_keysym(NULL, QEMU_KEY_END);
+ qemu_text_console_put_keysym(con, QEMU_KEY_END);
break;
case 0xc9:
- qemu_text_console_put_keysym(NULL, QEMU_KEY_PAGEUP);
+ qemu_text_console_put_keysym(con, QEMU_KEY_PAGEUP);
break;
case 0xd1:
- qemu_text_console_put_keysym(NULL, QEMU_KEY_PAGEDOWN);
+ qemu_text_console_put_keysym(con, QEMU_KEY_PAGEDOWN);
break;
case 0x47:
- qemu_text_console_put_keysym(NULL, numlock ? '7' : QEMU_KEY_HOME);
+ qemu_text_console_put_keysym(con, numlock ? '7' : QEMU_KEY_HOME);
break;
case 0x48:
- qemu_text_console_put_keysym(NULL, numlock ? '8' : QEMU_KEY_UP);
+ qemu_text_console_put_keysym(con, numlock ? '8' : QEMU_KEY_UP);
break;
case 0x49:
- qemu_text_console_put_keysym(NULL, numlock ? '9' : QEMU_KEY_PAGEUP);
+ qemu_text_console_put_keysym(con, numlock ? '9' : QEMU_KEY_PAGEUP);
break;
case 0x4b:
- qemu_text_console_put_keysym(NULL, numlock ? '4' : QEMU_KEY_LEFT);
+ qemu_text_console_put_keysym(con, numlock ? '4' : QEMU_KEY_LEFT);
break;
case 0x4c:
- qemu_text_console_put_keysym(NULL, '5');
+ qemu_text_console_put_keysym(con, '5');
break;
case 0x4d:
- qemu_text_console_put_keysym(NULL, numlock ? '6' : QEMU_KEY_RIGHT);
+ qemu_text_console_put_keysym(con, numlock ? '6' : QEMU_KEY_RIGHT);
break;
case 0x4f:
- qemu_text_console_put_keysym(NULL, numlock ? '1' : QEMU_KEY_END);
+ qemu_text_console_put_keysym(con, numlock ? '1' : QEMU_KEY_END);
break;
case 0x50:
- qemu_text_console_put_keysym(NULL, numlock ? '2' : QEMU_KEY_DOWN);
+ qemu_text_console_put_keysym(con, numlock ? '2' : QEMU_KEY_DOWN);
break;
case 0x51:
- qemu_text_console_put_keysym(NULL, numlock ? '3' : QEMU_KEY_PAGEDOWN);
+ qemu_text_console_put_keysym(con, numlock ? '3' : QEMU_KEY_PAGEDOWN);
break;
case 0x52:
- qemu_text_console_put_keysym(NULL, '0');
+ qemu_text_console_put_keysym(con, '0');
break;
case 0x53:
- qemu_text_console_put_keysym(NULL, numlock ? '.' : QEMU_KEY_DELETE);
+ qemu_text_console_put_keysym(con, numlock ? '.' : QEMU_KEY_DELETE);
break;
case 0xb5:
- qemu_text_console_put_keysym(NULL, '/');
+ qemu_text_console_put_keysym(con, '/');
break;
case 0x37:
- qemu_text_console_put_keysym(NULL, '*');
+ qemu_text_console_put_keysym(con, '*');
break;
case 0x4a:
- qemu_text_console_put_keysym(NULL, '-');
+ qemu_text_console_put_keysym(con, '-');
break;
case 0x4e:
- qemu_text_console_put_keysym(NULL, '+');
+ qemu_text_console_put_keysym(con, '+');
break;
case 0x9c:
- qemu_text_console_put_keysym(NULL, '\n');
+ qemu_text_console_put_keysym(con, '\n');
break;
default:
if (control) {
- qemu_text_console_put_keysym(NULL, sym & 0x1f);
+ qemu_text_console_put_keysym(con, sym & 0x1f);
} else {
- qemu_text_console_put_keysym(NULL, sym);
+ qemu_text_console_put_keysym(con, sym);
}
break;
}
@@ -2044,7 +2045,7 @@ static void key_event(VncState *vs, int down, uint32_t sym)
int keycode;
int lsym = sym;
- if (lsym >= 'A' && lsym <= 'Z' && qemu_console_is_graphic(NULL)) {
+ if (lsym >= 'A' && lsym <= 'Z' && qemu_console_is_graphic(vs->vd->dcl.con)) {
lsym = lsym - 'A' + 'a';
}
--
2.44.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PULL 2/5] ui/dbus: factor out sending a scanout
2024-03-12 14:02 [PULL 0/5] UI patches marcandre.lureau
2024-03-12 14:02 ` [PULL 1/5] ui/vnc: Respect bound console marcandre.lureau
@ 2024-03-12 14:02 ` marcandre.lureau
2024-03-12 14:02 ` [PULL 3/5] ui/dbus: filter out pending messages when scanout marcandre.lureau
` (3 subsequent siblings)
5 siblings, 0 replies; 19+ messages in thread
From: marcandre.lureau @ 2024-03-12 14:02 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Marc-André Lureau, Gerd Hoffmann,
Michael S. Tsirkin
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
ui/dbus-listener.c | 35 +++++++++++++++++------------------
1 file changed, 17 insertions(+), 18 deletions(-)
diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
index 18f556aa73..3f4529dbbd 100644
--- a/ui/dbus-listener.c
+++ b/ui/dbus-listener.c
@@ -630,11 +630,26 @@ static void dbus_gfx_update_sub(DBusDisplayListener *ddl,
DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL);
}
+static void ddl_scanout(DBusDisplayListener *ddl)
+{
+ GVariant *v_data;
+
+ v_data = g_variant_new_from_data(
+ G_VARIANT_TYPE("ay"), surface_data(ddl->ds),
+ surface_stride(ddl->ds) * surface_height(ddl->ds), TRUE,
+ (GDestroyNotify)pixman_image_unref, pixman_image_ref(ddl->ds->image));
+
+ qemu_dbus_display1_listener_call_scanout(
+ ddl->proxy, surface_width(ddl->ds), surface_height(ddl->ds),
+ surface_stride(ddl->ds), surface_format(ddl->ds), v_data,
+ G_DBUS_CALL_FLAGS_NONE, DBUS_DEFAULT_TIMEOUT, NULL, NULL,
+ g_object_ref(ddl));
+}
+
static void dbus_gfx_update(DisplayChangeListener *dcl,
int x, int y, int w, int h)
{
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
- GVariant *v_data;
assert(ddl->ds);
@@ -652,23 +667,7 @@ static void dbus_gfx_update(DisplayChangeListener *dcl,
#endif
if (x == 0 && y == 0 && w == surface_width(ddl->ds) && h == surface_height(ddl->ds)) {
- v_data = g_variant_new_from_data(
- G_VARIANT_TYPE("ay"),
- surface_data(ddl->ds),
- surface_stride(ddl->ds) * surface_height(ddl->ds),
- TRUE,
- (GDestroyNotify)pixman_image_unref,
- pixman_image_ref(ddl->ds->image));
- qemu_dbus_display1_listener_call_scanout(
- ddl->proxy,
- surface_width(ddl->ds),
- surface_height(ddl->ds),
- surface_stride(ddl->ds),
- surface_format(ddl->ds),
- v_data,
- G_DBUS_CALL_FLAGS_NONE,
- DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL);
- return;
+ return ddl_scanout(ddl);
}
dbus_gfx_update_sub(ddl, x, y, w, h);
--
2.44.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PULL 3/5] ui/dbus: filter out pending messages when scanout
2024-03-12 14:02 [PULL 0/5] UI patches marcandre.lureau
2024-03-12 14:02 ` [PULL 1/5] ui/vnc: Respect bound console marcandre.lureau
2024-03-12 14:02 ` [PULL 2/5] ui/dbus: factor out sending a scanout marcandre.lureau
@ 2024-03-12 14:02 ` marcandre.lureau
2024-03-12 14:02 ` [PULL 4/5] virtio-gpu: remove needless condition marcandre.lureau
` (2 subsequent siblings)
5 siblings, 0 replies; 19+ messages in thread
From: marcandre.lureau @ 2024-03-12 14:02 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Marc-André Lureau, Gerd Hoffmann,
Michael S. Tsirkin
From: Marc-André Lureau <marcandre.lureau@redhat.com>
The "Listener" connection, being private and under the control of the
qemu display, allows for the optimization of discarding pending
intermediary messages when queuing a new scanout. This ensures that the
client receives only the latest scanout update, improving communication
efficiency.
While the current implementation does not provide a mechanism for
clients who may wish to receive all updates, making this behavior
optional could be considered in the future. For now, adopting this new
default behavior accelerates the communication process without a
guarantee of delivering all updates.
The filter is removed when the connection is dropped.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
ui/dbus-listener.c | 40 ++++++++++++++++++++++++++++++++++++++++
ui/trace-events | 1 +
2 files changed, 41 insertions(+)
diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
index 3f4529dbbd..4a0a5d78f9 100644
--- a/ui/dbus-listener.c
+++ b/ui/dbus-listener.c
@@ -83,6 +83,9 @@ struct _DBusDisplayListener {
egl_fb fb;
#endif
#endif
+
+ guint dbus_filter;
+ guint32 out_serial_to_discard;
};
G_DEFINE_TYPE(DBusDisplayListener, dbus_display_listener, G_TYPE_OBJECT)
@@ -90,6 +93,12 @@ G_DEFINE_TYPE(DBusDisplayListener, dbus_display_listener, G_TYPE_OBJECT)
static void dbus_gfx_update(DisplayChangeListener *dcl,
int x, int y, int w, int h);
+static void ddl_discard_pending_messages(DBusDisplayListener *ddl)
+{
+ ddl->out_serial_to_discard = g_dbus_connection_get_last_serial(
+ g_dbus_proxy_get_connection(G_DBUS_PROXY(ddl->proxy)));
+}
+
#ifdef CONFIG_OPENGL
static void dbus_scanout_disable(DisplayChangeListener *dcl)
{
@@ -276,6 +285,8 @@ static void dbus_scanout_dmabuf(DisplayChangeListener *dcl,
return;
}
+ ddl_discard_pending_messages(ddl);
+
/* FIXME: add missing x/y/w/h support */
qemu_dbus_display1_listener_call_scanout_dmabuf(
ddl->proxy,
@@ -323,6 +334,8 @@ static bool dbus_scanout_map(DBusDisplayListener *ddl)
return false;
}
+ ddl_discard_pending_messages(ddl);
+
if (!qemu_dbus_display1_listener_win32_map_call_scanout_map_sync(
ddl->map_proxy,
GPOINTER_TO_UINT(target_handle),
@@ -384,6 +397,8 @@ dbus_scanout_share_d3d_texture(
return false;
}
+ ddl_discard_pending_messages(ddl);
+
qemu_dbus_display1_listener_win32_d3d11_call_scanout_texture2d(
ddl->d3d11_proxy,
GPOINTER_TO_INT(target_handle),
@@ -639,6 +654,8 @@ static void ddl_scanout(DBusDisplayListener *ddl)
surface_stride(ddl->ds) * surface_height(ddl->ds), TRUE,
(GDestroyNotify)pixman_image_unref, pixman_image_ref(ddl->ds->image));
+ ddl_discard_pending_messages(ddl);
+
qemu_dbus_display1_listener_call_scanout(
ddl->proxy, surface_width(ddl->ds), surface_height(ddl->ds),
surface_stride(ddl->ds), surface_format(ddl->ds), v_data,
@@ -963,6 +980,28 @@ dbus_display_listener_setup_shared_map(DBusDisplayListener *ddl)
#endif
}
+static GDBusMessage *
+dbus_filter(GDBusConnection *connection,
+ GDBusMessage *message,
+ gboolean incoming,
+ gpointer user_data)
+{
+ DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(user_data);
+ guint32 serial;
+
+ if (incoming) {
+ return message;
+ }
+
+ serial = g_dbus_message_get_serial(message);
+ if (serial <= ddl->out_serial_to_discard) {
+ trace_dbus_filter(serial, ddl->out_serial_to_discard);
+ return NULL;
+ }
+
+ return message;
+}
+
DBusDisplayListener *
dbus_display_listener_new(const char *bus_name,
GDBusConnection *conn,
@@ -987,6 +1026,7 @@ dbus_display_listener_new(const char *bus_name,
return NULL;
}
+ ddl->dbus_filter = g_dbus_connection_add_filter(conn, dbus_filter, g_object_ref(ddl), g_object_unref);
ddl->bus_name = g_strdup(bus_name);
ddl->conn = conn;
ddl->console = console;
diff --git a/ui/trace-events b/ui/trace-events
index 16c35c9fd6..e6a2894303 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -161,6 +161,7 @@ dbus_clipboard_register(const char *bus_name) "peer %s"
dbus_clipboard_unregister(const char *bus_name) "peer %s"
dbus_scanout_texture(uint32_t tex_id, bool backing_y_0_top, uint32_t backing_width, uint32_t backing_height, uint32_t x, uint32_t y, uint32_t w, uint32_t h) "tex_id:%u y0top:%d back:%ux%u %u+%u-%ux%u"
dbus_gl_gfx_switch(void *p) "surf: %p"
+dbus_filter(unsigned int serial, unsigned int filter) "serial=%u (<= %u)"
# egl-helpers.c
egl_init_d3d11_device(void *p) "d3d device: %p"
--
2.44.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PULL 4/5] virtio-gpu: remove needless condition
2024-03-12 14:02 [PULL 0/5] UI patches marcandre.lureau
` (2 preceding siblings ...)
2024-03-12 14:02 ` [PULL 3/5] ui/dbus: filter out pending messages when scanout marcandre.lureau
@ 2024-03-12 14:02 ` marcandre.lureau
2024-03-12 14:02 ` [PULL 5/5] virtio-gpu: fix scanout migration post-load marcandre.lureau
2024-03-12 21:32 ` [PULL 0/5] UI patches Peter Maydell
5 siblings, 0 replies; 19+ messages in thread
From: marcandre.lureau @ 2024-03-12 14:02 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Marc-André Lureau, Gerd Hoffmann,
Michael S. Tsirkin
From: Marc-André Lureau <marcandre.lureau@redhat.com>
qemu_create_displaysurface_pixman() never returns NULL.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hw/display/virtio-gpu.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 1c1ee230b3..ccbe31d759 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -684,10 +684,6 @@ static void virtio_gpu_do_set_scanout(VirtIOGPU *g,
/* realloc the surface ptr */
scanout->ds = qemu_create_displaysurface_pixman(rect);
- if (!scanout->ds) {
- *error = VIRTIO_GPU_RESP_ERR_UNSPEC;
- return;
- }
#ifdef WIN32
qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, fb->offset);
#endif
@@ -1423,9 +1419,6 @@ static int virtio_gpu_post_load(void *opaque, int version_id)
return -EINVAL;
}
scanout->ds = qemu_create_displaysurface_pixman(res->image);
- if (!scanout->ds) {
- return -EINVAL;
- }
#ifdef WIN32
qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 0);
#endif
--
2.44.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PULL 5/5] virtio-gpu: fix scanout migration post-load
2024-03-12 14:02 [PULL 0/5] UI patches marcandre.lureau
` (3 preceding siblings ...)
2024-03-12 14:02 ` [PULL 4/5] virtio-gpu: remove needless condition marcandre.lureau
@ 2024-03-12 14:02 ` marcandre.lureau
2024-04-30 12:30 ` Fiona Ebner
2024-03-12 21:32 ` [PULL 0/5] UI patches Peter Maydell
5 siblings, 1 reply; 19+ messages in thread
From: marcandre.lureau @ 2024-03-12 14:02 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Marc-André Lureau, Gerd Hoffmann,
Michael S. Tsirkin
From: Marc-André Lureau <marcandre.lureau@redhat.com>
The current post-loading code for scanout has a FIXME: it doesn't take
the resource region/rect into account. But there is more, when adding
blob migration support in commit f66767f75c9, I didn't realize that blob
resources could be used for scanouts. This situationn leads to a crash
during post-load, as they don't have an associated res->image.
virtio_gpu_do_set_scanout() handle all cases, but requires the
associated virtio_gpu_framebuffer, which is currently not saved during
migration.
Add a v2 of "virtio-gpu-one-scanout" with the framebuffer fields, so we
can restore blob scanouts, as well as fixing the existing FIXME.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Sebastian Ott <sebott@redhat.com>
---
include/hw/virtio/virtio-gpu.h | 1 +
hw/display/virtio-gpu.c | 51 +++++++++++++++++++++++++++-------
2 files changed, 42 insertions(+), 10 deletions(-)
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index b28e7ef0d2..ed44cdad6b 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -81,6 +81,7 @@ struct virtio_gpu_scanout {
uint32_t resource_id;
struct virtio_gpu_update_cursor cursor;
QEMUCursor *current_cursor;
+ struct virtio_gpu_framebuffer fb;
};
struct virtio_gpu_requested_state {
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index ccbe31d759..78d5a4f164 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -600,6 +600,7 @@ static void virtio_unref_resource(pixman_image_t *image, void *data)
static void virtio_gpu_update_scanout(VirtIOGPU *g,
uint32_t scanout_id,
struct virtio_gpu_simple_resource *res,
+ struct virtio_gpu_framebuffer *fb,
struct virtio_gpu_rect *r)
{
struct virtio_gpu_simple_resource *ores;
@@ -617,9 +618,10 @@ static void virtio_gpu_update_scanout(VirtIOGPU *g,
scanout->y = r->y;
scanout->width = r->width;
scanout->height = r->height;
+ scanout->fb = *fb;
}
-static void virtio_gpu_do_set_scanout(VirtIOGPU *g,
+static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
uint32_t scanout_id,
struct virtio_gpu_framebuffer *fb,
struct virtio_gpu_simple_resource *res,
@@ -645,7 +647,7 @@ static void virtio_gpu_do_set_scanout(VirtIOGPU *g,
r->x, r->y, r->width, r->height,
fb->width, fb->height);
*error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
- return;
+ return false;
}
g->parent_obj.enable = 1;
@@ -653,11 +655,12 @@ static void virtio_gpu_do_set_scanout(VirtIOGPU *g,
if (res->blob) {
if (console_has_gl(scanout->con)) {
if (!virtio_gpu_update_dmabuf(g, scanout_id, res, fb, r)) {
- virtio_gpu_update_scanout(g, scanout_id, res, r);
+ virtio_gpu_update_scanout(g, scanout_id, res, fb, r);
} else {
*error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
+ return false;
}
- return;
+ return true;
}
data = res->blob;
@@ -693,7 +696,8 @@ static void virtio_gpu_do_set_scanout(VirtIOGPU *g,
scanout->ds);
}
- virtio_gpu_update_scanout(g, scanout_id, res, r);
+ virtio_gpu_update_scanout(g, scanout_id, res, fb, r);
+ return true;
}
static void virtio_gpu_set_scanout(VirtIOGPU *g,
@@ -1164,7 +1168,8 @@ static void virtio_gpu_cursor_bh(void *opaque)
static const VMStateDescription vmstate_virtio_gpu_scanout = {
.name = "virtio-gpu-one-scanout",
- .version_id = 1,
+ .version_id = 2,
+ .minimum_version_id = 1,
.fields = (const VMStateField[]) {
VMSTATE_UINT32(resource_id, struct virtio_gpu_scanout),
VMSTATE_UINT32(width, struct virtio_gpu_scanout),
@@ -1176,6 +1181,12 @@ static const VMStateDescription vmstate_virtio_gpu_scanout = {
VMSTATE_UINT32(cursor.hot_y, struct virtio_gpu_scanout),
VMSTATE_UINT32(cursor.pos.x, struct virtio_gpu_scanout),
VMSTATE_UINT32(cursor.pos.y, struct virtio_gpu_scanout),
+ VMSTATE_UINT32_V(fb.format, struct virtio_gpu_scanout, 2),
+ VMSTATE_UINT32_V(fb.bytes_pp, struct virtio_gpu_scanout, 2),
+ VMSTATE_UINT32_V(fb.width, struct virtio_gpu_scanout, 2),
+ VMSTATE_UINT32_V(fb.height, struct virtio_gpu_scanout, 2),
+ VMSTATE_UINT32_V(fb.stride, struct virtio_gpu_scanout, 2),
+ VMSTATE_UINT32_V(fb.offset, struct virtio_gpu_scanout, 2),
VMSTATE_END_OF_LIST()
},
};
@@ -1347,6 +1358,7 @@ static int virtio_gpu_blob_save(QEMUFile *f, void *opaque, size_t size,
if (!res->blob_size) {
continue;
}
+ assert(!res->image);
qemu_put_be32(f, res->resource_id);
qemu_put_be32(f, res->blob_size);
qemu_put_be32(f, res->iov_cnt);
@@ -1409,21 +1421,40 @@ static int virtio_gpu_post_load(void *opaque, int version_id)
int i;
for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
- /* FIXME: should take scanout.r.{x,y} into account */
scanout = &g->parent_obj.scanout[i];
if (!scanout->resource_id) {
continue;
}
+
res = virtio_gpu_find_resource(g, scanout->resource_id);
if (!res) {
return -EINVAL;
}
- scanout->ds = qemu_create_displaysurface_pixman(res->image);
+
+ if (scanout->fb.format != 0) {
+ uint32_t error = 0;
+ struct virtio_gpu_rect r = {
+ .x = scanout->x,
+ .y = scanout->y,
+ .width = scanout->width,
+ .height = scanout->height
+ };
+
+ if (!virtio_gpu_do_set_scanout(g, i, &scanout->fb, res, &r, &error)) {
+ return -EINVAL;
+ }
+ } else {
+ /* legacy v1 migration support */
+ if (!res->image) {
+ return -EINVAL;
+ }
+ scanout->ds = qemu_create_displaysurface_pixman(res->image);
#ifdef WIN32
- qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 0);
+ qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 0);
#endif
+ dpy_gfx_replace_surface(scanout->con, scanout->ds);
+ }
- dpy_gfx_replace_surface(scanout->con, scanout->ds);
dpy_gfx_update_full(scanout->con);
if (scanout->cursor.resource_id) {
update_cursor(g, &scanout->cursor);
--
2.44.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PULL 5/5] virtio-gpu: fix scanout migration post-load
2024-03-12 14:02 ` [PULL 5/5] virtio-gpu: fix scanout migration post-load marcandre.lureau
@ 2024-04-30 12:30 ` Fiona Ebner
2024-05-01 14:55 ` Peter Xu
2024-05-07 10:14 ` Marc-André Lureau
0 siblings, 2 replies; 19+ messages in thread
From: Fiona Ebner @ 2024-04-30 12:30 UTC (permalink / raw)
To: marcandre.lureau, qemu-devel
Cc: peter.maydell, Gerd Hoffmann, Michael S. Tsirkin
Am 12.03.24 um 15:02 schrieb marcandre.lureau@redhat.com:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> The current post-loading code for scanout has a FIXME: it doesn't take
> the resource region/rect into account. But there is more, when adding
> blob migration support in commit f66767f75c9, I didn't realize that blob
> resources could be used for scanouts. This situationn leads to a crash
> during post-load, as they don't have an associated res->image.
>
> virtio_gpu_do_set_scanout() handle all cases, but requires the
> associated virtio_gpu_framebuffer, which is currently not saved during
> migration.
>
> Add a v2 of "virtio-gpu-one-scanout" with the framebuffer fields, so we
> can restore blob scanouts, as well as fixing the existing FIXME.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Sebastian Ott <sebott@redhat.com>
Hi,
unfortunately, this broke migration from pre-9.0 to 9.0:
> vmstate_load_state_field virtio-gpu:virtio-gpu
> vmstate_load_state_field virtio-gpu-scanouts:parent_obj.enable
> vmstate_load_state_field virtio-gpu-scanouts:parent_obj.conf.max_outputs
> vmstate_load_state_field virtio-gpu-scanouts:parent_obj.scanout
> vmstate_load_state_field virtio-gpu-one-scanout:resource_id
> vmstate_load_state_field virtio-gpu-one-scanout:width
> vmstate_load_state_field virtio-gpu-one-scanout:height
> vmstate_load_state_field virtio-gpu-one-scanout:x
> vmstate_load_state_field virtio-gpu-one-scanout:y
> vmstate_load_state_field virtio-gpu-one-scanout:cursor.resource_id
> vmstate_load_state_field virtio-gpu-one-scanout:cursor.hot_x
> vmstate_load_state_field virtio-gpu-one-scanout:cursor.hot_y
> vmstate_load_state_field virtio-gpu-one-scanout:cursor.pos.x
> vmstate_load_state_field virtio-gpu-one-scanout:cursor.pos.y
> vmstate_load_state_field virtio-gpu-one-scanout:fb.format
> vmstate_load_state_field virtio-gpu-one-scanout:fb.bytes_pp
> vmstate_load_state_field virtio-gpu-one-scanout:fb.width
> vmstate_load_state_field virtio-gpu-one-scanout:fb.height
> vmstate_load_state_field virtio-gpu-one-scanout:fb.stride
> vmstate_load_state_field virtio-gpu-one-scanout:fb.offset
> qemu-system-x86_64: Missing section footer for 0000:00:02.0/virtio-gpu
> qemu-system-x86_64: Error -22 while loading VM state
It wrongly tries to load the fb fields even though they should be
guarded by version 2.
Looking at it with GDB, in vmstate_load_state(), when we come to
field->name == parent_obj.scanout, the
> } else if (field->flags & VMS_STRUCT) {
> ret = vmstate_load_state(f, field->vmsd, curr_elem,
> field->vmsd->version_id);
branch will be taken and suddenly we'll have a call to
vmstate_load_state() for vmsd==vmstate_virtio_gpu_scanout with
version_id==2 rather than version_id==1, because that is
field->vmsd->version_id (i.e. the .version_id in VMStateDescription
vmstate_virtio_gpu_scanout).
Would it have been necessary to version the VMStateDescription
vmstate_virtio_gpu_scanouts too using VMS_VSTRUCT (or am I
misinterpreting the use case for that)?
Best Regards,
Fiona
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PULL 5/5] virtio-gpu: fix scanout migration post-load
2024-04-30 12:30 ` Fiona Ebner
@ 2024-05-01 14:55 ` Peter Xu
2024-05-07 10:14 ` Marc-André Lureau
1 sibling, 0 replies; 19+ messages in thread
From: Peter Xu @ 2024-05-01 14:55 UTC (permalink / raw)
To: Fiona Ebner
Cc: marcandre.lureau, qemu-devel, peter.maydell, Gerd Hoffmann,
Michael S. Tsirkin, Fabiano Rosas
On Tue, Apr 30, 2024 at 02:30:19PM +0200, Fiona Ebner wrote:
> Am 12.03.24 um 15:02 schrieb marcandre.lureau@redhat.com:
> > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> >
> > The current post-loading code for scanout has a FIXME: it doesn't take
> > the resource region/rect into account. But there is more, when adding
> > blob migration support in commit f66767f75c9, I didn't realize that blob
> > resources could be used for scanouts. This situationn leads to a crash
> > during post-load, as they don't have an associated res->image.
> >
> > virtio_gpu_do_set_scanout() handle all cases, but requires the
> > associated virtio_gpu_framebuffer, which is currently not saved during
> > migration.
> >
> > Add a v2 of "virtio-gpu-one-scanout" with the framebuffer fields, so we
> > can restore blob scanouts, as well as fixing the existing FIXME.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > Reviewed-by: Sebastian Ott <sebott@redhat.com>
>
> Hi,
> unfortunately, this broke migration from pre-9.0 to 9.0:
>
> > vmstate_load_state_field virtio-gpu:virtio-gpu
> > vmstate_load_state_field virtio-gpu-scanouts:parent_obj.enable
> > vmstate_load_state_field virtio-gpu-scanouts:parent_obj.conf.max_outputs
> > vmstate_load_state_field virtio-gpu-scanouts:parent_obj.scanout
> > vmstate_load_state_field virtio-gpu-one-scanout:resource_id
> > vmstate_load_state_field virtio-gpu-one-scanout:width
> > vmstate_load_state_field virtio-gpu-one-scanout:height
> > vmstate_load_state_field virtio-gpu-one-scanout:x
> > vmstate_load_state_field virtio-gpu-one-scanout:y
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.resource_id
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.hot_x
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.hot_y
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.pos.x
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.pos.y
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.format
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.bytes_pp
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.width
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.height
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.stride
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.offset
> > qemu-system-x86_64: Missing section footer for 0000:00:02.0/virtio-gpu
> > qemu-system-x86_64: Error -22 while loading VM state
>
> It wrongly tries to load the fb fields even though they should be
> guarded by version 2.
>
> Looking at it with GDB, in vmstate_load_state(), when we come to
> field->name == parent_obj.scanout, the
>
> > } else if (field->flags & VMS_STRUCT) {
> > ret = vmstate_load_state(f, field->vmsd, curr_elem,
> > field->vmsd->version_id);
>
> branch will be taken and suddenly we'll have a call to
> vmstate_load_state() for vmsd==vmstate_virtio_gpu_scanout with
> version_id==2 rather than version_id==1, because that is
> field->vmsd->version_id (i.e. the .version_id in VMStateDescription
> vmstate_virtio_gpu_scanout).
>
> Would it have been necessary to version the VMStateDescription
> vmstate_virtio_gpu_scanouts too using VMS_VSTRUCT (or am I
> misinterpreting the use case for that)?
Looks right. And there's only one such user which is when it's introduced
in 2018. It's sad we can't simply already use vmsd subsections even if
that was there before this VSTRUCT thing, and that should work with
internal versioning. Maybe we introduced that because we can't replace a
VMS_STRUCT to subsections?
https://lore.kernel.org/qemu-devel/1524670052-28373-1-git-send-email-minyard@acm.org/#t
OTOH, I don't think vmsd versioning would work for ping-pong migrations.
Migrating backwards should fail with 'not supported' with vmsd versionings.
Depending on the requirement (in this virtio-gpu case, it looks like
applicable to be used in a cluster and doing back-and-forth moves?), we may
want to support bi-directional migrations which should be superior. That
will need to stick with machine type check (compat fields in hw_compat_*,
then conditionally save/load fields) to guarantee migration can work back
and forth.
Thanks,
--
Peter Xu
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PULL 5/5] virtio-gpu: fix scanout migration post-load
2024-04-30 12:30 ` Fiona Ebner
2024-05-01 14:55 ` Peter Xu
@ 2024-05-07 10:14 ` Marc-André Lureau
1 sibling, 0 replies; 19+ messages in thread
From: Marc-André Lureau @ 2024-05-07 10:14 UTC (permalink / raw)
To: Fiona Ebner, Gerd Hoffmann, Sebastian Ott, peter.maydell,
Richard Henderson
Cc: qemu-devel, Michael S. Tsirkin
Hi
On Tue, Apr 30, 2024 at 4:31 PM Fiona Ebner <f.ebner@proxmox.com> wrote:
>
> Am 12.03.24 um 15:02 schrieb marcandre.lureau@redhat.com:
> > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> >
> > The current post-loading code for scanout has a FIXME: it doesn't take
> > the resource region/rect into account. But there is more, when adding
> > blob migration support in commit f66767f75c9, I didn't realize that blob
> > resources could be used for scanouts. This situationn leads to a crash
> > during post-load, as they don't have an associated res->image.
> >
> > virtio_gpu_do_set_scanout() handle all cases, but requires the
> > associated virtio_gpu_framebuffer, which is currently not saved during
> > migration.
> >
> > Add a v2 of "virtio-gpu-one-scanout" with the framebuffer fields, so we
> > can restore blob scanouts, as well as fixing the existing FIXME.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > Reviewed-by: Sebastian Ott <sebott@redhat.com>
>
> Hi,
> unfortunately, this broke migration from pre-9.0 to 9.0:
>
> > vmstate_load_state_field virtio-gpu:virtio-gpu
> > vmstate_load_state_field virtio-gpu-scanouts:parent_obj.enable
> > vmstate_load_state_field virtio-gpu-scanouts:parent_obj.conf.max_outputs
> > vmstate_load_state_field virtio-gpu-scanouts:parent_obj.scanout
> > vmstate_load_state_field virtio-gpu-one-scanout:resource_id
> > vmstate_load_state_field virtio-gpu-one-scanout:width
> > vmstate_load_state_field virtio-gpu-one-scanout:height
> > vmstate_load_state_field virtio-gpu-one-scanout:x
> > vmstate_load_state_field virtio-gpu-one-scanout:y
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.resource_id
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.hot_x
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.hot_y
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.pos.x
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.pos.y
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.format
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.bytes_pp
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.width
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.height
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.stride
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.offset
> > qemu-system-x86_64: Missing section footer for 0000:00:02.0/virtio-gpu
> > qemu-system-x86_64: Error -22 while loading VM state
>
> It wrongly tries to load the fb fields even though they should be
> guarded by version 2.
>
> Looking at it with GDB, in vmstate_load_state(), when we come to
> field->name == parent_obj.scanout, the
>
> > } else if (field->flags & VMS_STRUCT) {
> > ret = vmstate_load_state(f, field->vmsd, curr_elem,
> > field->vmsd->version_id);
>
> branch will be taken and suddenly we'll have a call to
> vmstate_load_state() for vmsd==vmstate_virtio_gpu_scanout with
> version_id==2 rather than version_id==1, because that is
> field->vmsd->version_id (i.e. the .version_id in VMStateDescription
> vmstate_virtio_gpu_scanout).
>
> Would it have been necessary to version the VMStateDescription
> vmstate_virtio_gpu_scanouts too using VMS_VSTRUCT (or am I
> misinterpreting the use case for that)?
>
Sigh.. this is embarrassing. This patch didn't receive enough testing
and breaks pre-9.0/9.0 forward and backward migrations.
I think it would be reasonable to revert the patch, but it's already
in 9.0. Is that acceptable?
There are various issues about versioning:
- VMStateDescription (vmsd) version_id are not in the stream (only
start & full section headers), so any nested version bump should
somehow be bubbled up/down..
- machine versions don't have specific vmsd version_id associations
(that I can see, or is there any way to do that?)
- virtio-gpu uses even lower-level vmstate API and hardcodes version
to 1 in general
Ideally, I wished adding versionized fields the way done in this patch
would simply work, but this is really, sadly, not supported atm.
And it would be great to have some testing for back/forward migrations.
Any thoughts, corrections, encouragement perhaps? :)
thanks
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PULL 0/5] UI patches
2024-03-12 14:02 [PULL 0/5] UI patches marcandre.lureau
` (4 preceding siblings ...)
2024-03-12 14:02 ` [PULL 5/5] virtio-gpu: fix scanout migration post-load marcandre.lureau
@ 2024-03-12 21:32 ` Peter Maydell
5 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2024-03-12 21:32 UTC (permalink / raw)
To: marcandre.lureau; +Cc: qemu-devel, Gerd Hoffmann, Michael S. Tsirkin
On Tue, 12 Mar 2024 at 14:02, <marcandre.lureau@redhat.com> wrote:
>
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> The following changes since commit 8f3f329f5e0117bd1a23a79ab751f8a7d3471e4b:
>
> Merge tag 'migration-20240311-pull-request' of https://gitlab.com/peterx/qemu into staging (2024-03-12 11:35:41 +0000)
>
> are available in the Git repository at:
>
> https://gitlab.com/marcandre.lureau/qemu.git tags/ui-pull-request
>
> for you to fetch changes up to dfcf74fa68c88233209aafc5f82728d0b9a1af5c:
>
> virtio-gpu: fix scanout migration post-load (2024-03-12 17:57:58 +0400)
>
> ----------------------------------------------------------------
> display/ui: pending fixes
>
> - ui/vnc: Respect bound console
> - ui/dbus: optimize a bit message queuing
> - virtio-gpu: fix blob scanout post-load
>
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/9.0
for any user-visible changes.
-- PMM
^ permalink raw reply [flat|nested] 19+ messages in thread