aboutsummaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2022-09-27 07:59:26 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2022-09-27 07:59:26 -0400
commitc48c9c6b33d7bb2b4ffa14cd33934a37db0cd342 (patch)
treebb763292e349b646299433099c8e69490df42f3a /ui
parent8b077615b3fd3041c6e7105ec3a178a2a0ed3cad (diff)
parent49a99ecb2290571b2e3f464c13e9c73b87ca91c4 (diff)
downloadqemu-c48c9c6b33d7bb2b4ffa14cd33934a37db0cd342.zip
qemu-c48c9c6b33d7bb2b4ffa14cd33934a37db0cd342.tar.gz
qemu-c48c9c6b33d7bb2b4ffa14cd33934a37db0cd342.tar.bz2
Merge tag 'kraxel-20220927-pull-request' of https://gitlab.com/kraxel/qemu into staging
usb: make usbnet work with xhci. audio: add sndio backend. misc bugfixes for console, xhci, audio, ati-vga and virtio-gpu. # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEEoDKM/7k6F6eZAf59TLbY7tPocTgFAmMyse8ACgkQTLbY7tPo # cTiLrRAAltoyd++jsmhg2wXuJsfekfec3kOro7T+eSznDWfBRvm7VxJ+gswYBYga # HbEkHjII0yPbOP9WDMhhHx33g2nYdbhDLPKXHdK8MjHTTPxtYP7XmsWkEVpuuzTx # WqeYvGSmUri6QOUz7fd07IhiBT1aQvUQ/vWQ6OhyRVPy41bR8kIbGx3iV0JDxWvz # n3xUZALGLz3QAM0lXRzXPYT9JB/RqdbpMM35HNTpN9/xaZmgFWsyuQXSSm61pTtb # PS+lILDPjgZeYsfsZRyhZaSZrp2f6WOGm1ZdtSM0rvmRKezOzYnG8fm4fqZQLYSj # nrAqUs38sKaM71a3QbpXhDjbv4cpj0K3iSNLmlUq4pgvPiMgwPlgSwwCGlkNDaRo # IA1KON1pMH2A5vvtXEUt5RTkbXxHAAKPdpl5sS6kgbs7dgoKDqzaIPFQELam259Z # 9nbMBqz/d6gm2CFT5ogrY0q511IC5hWtsmbQZkOZeBd5SvhvyJ59DIabFDcw05fG # ixZVapewXYtzFUde2lb8X5qyneUVeGY5D2OJ2uUykHgR2Qz4d3CjXlhnRkLIkMcd # Uu6N1LTkjyuuB86BoTSZxk0iz94OvmyDiXpqwmRaCGcdnTOTj0dKrbRrtHdC2vCo # cBpUAIdyJvDJSm0X8ZWvvv1sMJCAJ7lofFf/P/jUKlacC2ipgXQ= # =QBLK # -----END PGP SIGNATURE----- # gpg: Signature made Tue 27 Sep 2022 04:18:55 EDT # 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 * tag 'kraxel-20220927-pull-request' of https://gitlab.com/kraxel/qemu: (24 commits) virtio-gpu: update scanout if there is any area covered by the rect hw/display/ati_2d: Fix buffer overflow in ati_2d_blt (CVE-2021-3638) audio: remove abort() in audio_bug() Revert "audio: Log context for audio bug" audio: Add sndio backend usbnet: Report link-up via interrupt endpoint in CDC-ECM mode usbnet: Detect short packets as sent by the xHCI controller usbnet: Accept mandatory USB_CDC_SET_ETHERNET_PACKET_FILTER request usbnet: Add missing usb_wakeup() call in usbnet_receive() hcd-xhci: drop operation with secondary stream arrays enabled usb/msd: add usb_msd_fatal_error() and fix guest-triggerable assert usb/msd: move usb_msd_packet_complete() hcd-ohci: Drop ohci_service_iso_td() if ed->head & OHCI_DPTR_MASK is zero hw/usb/hcd-xhci: Check whether DMA accesses fail ui/console: fix three double frees in png_save() ui/vdagent: fix serial reset of guest agent ui/clipboard: reset the serial state on reset ui/vdagent: always reset the clipboard serial on caps ui/clipboard: fix serial priority ui: add some vdagent related traces ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'ui')
-rw-r--r--ui/clipboard.c18
-rw-r--r--ui/cocoa.m144
-rw-r--r--ui/console.c6
-rw-r--r--ui/trace-events5
-rw-r--r--ui/vdagent.c13
5 files changed, 85 insertions, 101 deletions
diff --git a/ui/clipboard.c b/ui/clipboard.c
index 9079ef8..3d14bff 100644
--- a/ui/clipboard.c
+++ b/ui/clipboard.c
@@ -1,5 +1,6 @@
#include "qemu/osdep.h"
#include "ui/clipboard.h"
+#include "trace.h"
static NotifierList clipboard_notifiers =
NOTIFIER_LIST_INITIALIZER(clipboard_notifiers);
@@ -43,17 +44,23 @@ void qemu_clipboard_peer_release(QemuClipboardPeer *peer,
bool qemu_clipboard_check_serial(QemuClipboardInfo *info, bool client)
{
+ bool ok;
+
if (!info->has_serial ||
!cbinfo[info->selection] ||
!cbinfo[info->selection]->has_serial) {
+ trace_clipboard_check_serial(-1, -1, true);
return true;
}
if (client) {
- return cbinfo[info->selection]->serial >= info->serial;
+ ok = info->serial >= cbinfo[info->selection]->serial;
} else {
- return cbinfo[info->selection]->serial > info->serial;
+ ok = info->serial > cbinfo[info->selection]->serial;
}
+
+ trace_clipboard_check_serial(cbinfo[info->selection]->serial, info->serial, ok);
+ return ok;
}
void qemu_clipboard_update(QemuClipboardInfo *info)
@@ -132,7 +139,14 @@ void qemu_clipboard_request(QemuClipboardInfo *info,
void qemu_clipboard_reset_serial(void)
{
QemuClipboardNotify notify = { .type = QEMU_CLIPBOARD_RESET_SERIAL };
+ int i;
+ for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) {
+ QemuClipboardInfo *info = qemu_clipboard_info(i);
+ if (info) {
+ info->serial = 0;
+ }
+ }
notifier_list_notify(&clipboard_notifiers, &notify);
}
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 5a8bd5d..660d3e0 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -100,13 +100,9 @@ static int cursor_hide = 1;
static int left_command_key_enabled = 1;
static bool swap_opt_cmd;
-static int gArgc;
-static char **gArgv;
static bool stretch_video;
static NSTextField *pauseLabel;
-static QemuSemaphore display_init_sem;
-static QemuSemaphore app_started_sem;
static bool allow_events;
static NSInteger cbchangecount = -1;
@@ -597,7 +593,7 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
/*
* Don't try to tell QEMU about UI information in the application
* startup phase -- we haven't yet registered dcl with the QEMU UI
- * layer, and also trying to take the iothread lock would deadlock.
+ * layer.
* When cocoa_display_init() does register the dcl, the UI layer
* will call cocoa_switch(), which will call updateUIInfo, so
* we don't lose any information here.
@@ -790,16 +786,6 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
- (bool) handleEvent:(NSEvent *)event
{
- if(!allow_events) {
- /*
- * Just let OSX have all events that arrive before
- * applicationDidFinishLaunching.
- * This avoids a deadlock on the iothread lock, which cocoa_display_init()
- * will not drop until after the app_started_sem is posted. (In theory
- * there should not be any such events, but OSX Catalina now emits some.)
- */
- return false;
- }
return bool_with_iothread_lock(^{
return [self handleEventLocked:event];
});
@@ -1287,8 +1273,6 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
{
COCOA_DEBUG("QemuCocoaAppController: applicationDidFinishLaunching\n");
allow_events = true;
- /* Tell cocoa_display_init to proceed */
- qemu_sem_post(&app_started_sem);
}
- (void)applicationWillTerminate:(NSNotification *)aNotification
@@ -1919,92 +1903,45 @@ static void cocoa_clipboard_request(QemuClipboardInfo *info,
/*
* The startup process for the OSX/Cocoa UI is complicated, because
* OSX insists that the UI runs on the initial main thread, and so we
- * need to start a second thread which runs the vl.c qemu_main():
- *
- * Initial thread: 2nd thread:
+ * need to start a second thread which runs the qemu_default_main():
* in main():
- * create qemu-main thread
- * wait on display_init semaphore
- * call qemu_main()
- * ...
- * in cocoa_display_init():
- * post the display_init semaphore
- * wait on app_started semaphore
- * create application, menus, etc
- * enter OSX run loop
- * in applicationDidFinishLaunching:
- * post app_started semaphore
- * tell main thread to fullscreen if needed
- * [...]
- * run qemu main-loop
- *
- * We do this in two stages so that we don't do the creation of the
- * GUI application menus and so on for command line options like --help
- * where we want to just print text to stdout and exit immediately.
+ * in cocoa_display_init():
+ * assign cocoa_main to qemu_main
+ * create application, menus, etc
+ * in cocoa_main():
+ * create qemu-main thread
+ * enter OSX run loop
*/
static void *call_qemu_main(void *opaque)
{
int status;
- COCOA_DEBUG("Second thread: calling qemu_main()\n");
- status = qemu_main(gArgc, gArgv, *_NSGetEnviron());
- COCOA_DEBUG("Second thread: qemu_main() returned, exiting\n");
+ COCOA_DEBUG("Second thread: calling qemu_default_main()\n");
+ qemu_mutex_lock_iothread();
+ status = qemu_default_main();
+ qemu_mutex_unlock_iothread();
+ COCOA_DEBUG("Second thread: qemu_default_main() returned, exiting\n");
[cbowner release];
exit(status);
}
-int main (int argc, char **argv) {
+static int cocoa_main()
+{
QemuThread thread;
- COCOA_DEBUG("Entered main()\n");
- gArgc = argc;
- gArgv = argv;
-
- qemu_sem_init(&display_init_sem, 0);
- qemu_sem_init(&app_started_sem, 0);
+ COCOA_DEBUG("Entered %s()\n", __func__);
+ qemu_mutex_unlock_iothread();
qemu_thread_create(&thread, "qemu_main", call_qemu_main,
NULL, QEMU_THREAD_DETACHED);
- COCOA_DEBUG("Main thread: waiting for display_init_sem\n");
- qemu_sem_wait(&display_init_sem);
- COCOA_DEBUG("Main thread: initializing app\n");
-
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
- // Pull this console process up to being a fully-fledged graphical
- // app with a menubar and Dock icon
- ProcessSerialNumber psn = { 0, kCurrentProcess };
- TransformProcessType(&psn, kProcessTransformToForegroundApplication);
-
- [QemuApplication sharedApplication];
-
- create_initial_menus();
-
- /*
- * Create the menu entries which depend on QEMU state (for consoles
- * and removeable devices). These make calls back into QEMU functions,
- * which is OK because at this point we know that the second thread
- * holds the iothread lock and is synchronously waiting for us to
- * finish.
- */
- add_console_menu_entries();
- addRemovableDevicesMenuItems();
-
- // Create an Application controller
- QemuCocoaAppController *appController = [[QemuCocoaAppController alloc] init];
- [NSApp setDelegate:appController];
-
// Start the main event loop
COCOA_DEBUG("Main thread: entering OSX run loop\n");
[NSApp run];
- COCOA_DEBUG("Main thread: left OSX run loop, exiting\n");
+ COCOA_DEBUG("Main thread: left OSX run loop, which should never happen\n");
- [appController release];
- [pool release];
-
- return 0;
+ abort();
}
@@ -2083,25 +2020,42 @@ static void cocoa_refresh(DisplayChangeListener *dcl)
static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts)
{
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n");
- /* Tell main thread to go ahead and create the app and enter the run loop */
- qemu_sem_post(&display_init_sem);
- qemu_sem_wait(&app_started_sem);
- COCOA_DEBUG("cocoa_display_init: app start completed\n");
+ qemu_main = cocoa_main;
+
+ // Pull this console process up to being a fully-fledged graphical
+ // app with a menubar and Dock icon
+ ProcessSerialNumber psn = { 0, kCurrentProcess };
+ TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+
+ [QemuApplication sharedApplication];
+
+ create_initial_menus();
+
+ /*
+ * Create the menu entries which depend on QEMU state (for consoles
+ * and removeable devices). These make calls back into QEMU functions,
+ * which is OK because at this point we know that the second thread
+ * holds the iothread lock and is synchronously waiting for us to
+ * finish.
+ */
+ add_console_menu_entries();
+ addRemovableDevicesMenuItems();
+
+ // Create an Application controller
+ QemuCocoaAppController *controller = [[QemuCocoaAppController alloc] init];
+ [NSApp setDelegate:controller];
- QemuCocoaAppController *controller = (QemuCocoaAppController *)[[NSApplication sharedApplication] delegate];
/* if fullscreen mode is to be used */
if (opts->has_full_screen && opts->full_screen) {
- dispatch_async(dispatch_get_main_queue(), ^{
- [NSApp activateIgnoringOtherApps: YES];
- [controller toggleFullScreen: nil];
- });
+ [NSApp activateIgnoringOtherApps: YES];
+ [controller toggleFullScreen: nil];
}
if (opts->u.cocoa.has_full_grab && opts->u.cocoa.full_grab) {
- dispatch_async(dispatch_get_main_queue(), ^{
- [controller setFullGrab: nil];
- });
+ [controller setFullGrab: nil];
}
if (opts->has_show_cursor && opts->show_cursor) {
@@ -2121,6 +2075,8 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts)
qemu_event_init(&cbevent, false);
cbowner = [[QemuCocoaPasteboardTypeOwner alloc] init];
qemu_clipboard_peer_register(&cbpeer);
+
+ [pool release];
}
static QemuDisplay qemu_display_cocoa = {
diff --git a/ui/console.c b/ui/console.c
index 765892f..49da6a9 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -304,8 +304,8 @@ static bool png_save(int fd, pixman_image_t *image, Error **errp)
{
int width = pixman_image_get_width(image);
int height = pixman_image_get_height(image);
- g_autofree png_struct *png_ptr = NULL;
- g_autofree png_info *info_ptr = NULL;
+ png_struct *png_ptr;
+ png_info *info_ptr;
g_autoptr(pixman_image_t) linebuf =
qemu_pixman_linebuf_create(PIXMAN_a8r8g8b8, width);
uint8_t *buf = (uint8_t *)pixman_image_get_data(linebuf);
@@ -346,7 +346,6 @@ static bool png_save(int fd, pixman_image_t *image, Error **errp)
qemu_pixman_linebuf_fill(linebuf, image, width, 0, y);
png_write_row(png_ptr, buf);
}
- qemu_pixman_image_unref(linebuf);
png_write_end(png_ptr, NULL);
@@ -1368,6 +1367,7 @@ static const int qcode_to_keysym[Q_KEY_CODE__MAX] = {
[Q_KEY_CODE_PGUP] = QEMU_KEY_PAGEUP,
[Q_KEY_CODE_PGDN] = QEMU_KEY_PAGEDOWN,
[Q_KEY_CODE_DELETE] = QEMU_KEY_DELETE,
+ [Q_KEY_CODE_TAB] = QEMU_KEY_TAB,
[Q_KEY_CODE_BACKSPACE] = QEMU_KEY_BACKSPACE,
};
diff --git a/ui/trace-events b/ui/trace-events
index a922f00..977577f 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -127,15 +127,20 @@ xkeymap_vendor(const char *name) "vendor '%s'"
xkeymap_keycodes(const char *name) "keycodes '%s'"
xkeymap_keymap(const char *name) "keymap '%s'"
+# clipboard.c
+clipboard_check_serial(int cur, int recv, bool ok) "cur:%d recv:%d %d"
+
# vdagent.c
vdagent_open(void) ""
vdagent_close(void) ""
+vdagent_disconnect(void) ""
vdagent_send(const char *name) "msg %s"
vdagent_send_empty_clipboard(void) ""
vdagent_recv_chunk(uint32_t size) "size %d"
vdagent_recv_msg(const char *name, uint32_t size) "msg %s, size %d"
vdagent_peer_cap(const char *name) "cap %s"
vdagent_cb_grab_selection(const char *name) "selection %s"
+vdagent_cb_grab_discard(const char *name, int cur, int recv) "selection %s, cur:%d recv:%d"
vdagent_cb_grab_type(const char *name) "type %s"
vdagent_cb_serial_discard(uint32_t current, uint32_t received) "current=%u, received=%u"
diff --git a/ui/vdagent.c b/ui/vdagent.c
index a899eed..4bf50f0 100644
--- a/ui/vdagent.c
+++ b/ui/vdagent.c
@@ -471,7 +471,7 @@ static void vdagent_clipboard_reset_serial(VDAgentChardev *vd)
/* reopen the agent connection to reset the serial state */
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
- qemu_chr_be_event(chr, CHR_EVENT_OPENED);
+ /* OPENED again after the guest disconnected, see set_fe_open */
}
static void vdagent_clipboard_notify(Notifier *notifier, void *data)
@@ -533,6 +533,8 @@ static void vdagent_clipboard_recv_grab(VDAgentChardev *vd, uint8_t s, uint32_t
info->has_serial = true;
info->serial = *(uint32_t *)data;
if (info->serial < vd->last_serial[s]) {
+ trace_vdagent_cb_grab_discard(GET_NAME(sel_name, s),
+ vd->last_serial[s], info->serial);
/* discard lower-ordering guest grab */
return;
}
@@ -717,8 +719,10 @@ static void vdagent_chr_recv_caps(VDAgentChardev *vd, VDAgentMessage *msg)
if (have_mouse(vd) && vd->mouse_hs) {
qemu_input_handler_activate(vd->mouse_hs);
}
+
+ memset(vd->last_serial, 0, sizeof(vd->last_serial));
+
if (have_clipboard(vd) && vd->cbpeer.notifier.notify == NULL) {
- memset(vd->last_serial, 0, sizeof(vd->last_serial));
vd->cbpeer.name = "vdagent";
vd->cbpeer.notifier.notify = vdagent_clipboard_notify;
vd->cbpeer.request = vdagent_clipboard_request;
@@ -853,6 +857,8 @@ static void vdagent_chr_accept_input(Chardev *chr)
static void vdagent_disconnect(VDAgentChardev *vd)
{
+ trace_vdagent_disconnect();
+
buffer_reset(&vd->outbuf);
vdagent_reset_bufs(vd);
vd->caps = 0;
@@ -869,6 +875,9 @@ static void vdagent_chr_set_fe_open(struct Chardev *chr, int fe_open)
{
if (!fe_open) {
trace_vdagent_close();
+ /* To reset_serial, we CLOSED our side. Make sure the other end knows we
+ * are ready again. */
+ qemu_chr_be_event(chr, CHR_EVENT_OPENED);
return;
}