diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2022-09-27 07:59:26 -0400 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2022-09-27 07:59:26 -0400 |
commit | c48c9c6b33d7bb2b4ffa14cd33934a37db0cd342 (patch) | |
tree | bb763292e349b646299433099c8e69490df42f3a /ui | |
parent | 8b077615b3fd3041c6e7105ec3a178a2a0ed3cad (diff) | |
parent | 49a99ecb2290571b2e3f464c13e9c73b87ca91c4 (diff) | |
download | qemu-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.c | 18 | ||||
-rw-r--r-- | ui/cocoa.m | 144 | ||||
-rw-r--r-- | ui/console.c | 6 | ||||
-rw-r--r-- | ui/trace-events | 5 | ||||
-rw-r--r-- | ui/vdagent.c | 13 |
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, ¬ify); } @@ -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; } |