From 2297db8228cc0ee601a21b3e3f443ab6879f2a06 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Sat, 5 Mar 2022 19:45:21 +0900 Subject: [PATCH 1/6] ui/gtk: Ignore 2- and 3-button press events GTK already produces corresponding GDK_BUTTON_PRESS events alongside 2BUTTON and 3BUTTON_PRESS events. The 2BUTTON and 3BUTTON_PRESS events were incorrectly being interpreted and passed to guests as button release events. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/558 Signed-off-by: K. Lange Message-Id: <20220305104521.3583703-1-klange@toaruos.org> Signed-off-by: Gerd Hoffmann --- ui/gtk.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/gtk.c b/ui/gtk.c index 1b24a67d79..c57c36749e 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -972,6 +972,10 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button, return TRUE; } + if (button->type == GDK_2BUTTON_PRESS || button->type == GDK_3BUTTON_PRESS) { + return TRUE; + } + qemu_input_queue_btn(vc->gfx.dcl.con, btn, button->type == GDK_BUTTON_PRESS); qemu_input_event_sync(); From 6c08964b415a7bfd3b3ed65e7309cc3ffdb096b8 Mon Sep 17 00:00:00 2001 From: "Wen, Jianxian" Date: Tue, 15 Mar 2022 06:50:37 +0000 Subject: [PATCH 2/6] ui: avoid unnecessary memory operations in vnc_refresh_server_surface() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check the dirty bits in advance to avoid unnecessary memory operations. In the case that guest surface has different format than the server, but it does not have dirty bits which means no refresh is actually needed, the memory operations is not necessary. Signed-off-by: Jianxian Wen Signed-off-by: Lu Gao Reviewed-by: Marc-André Lureau Message-Id: <4C23C17B8E87E74E906A25A3254A03F4FA22100C@SHASXM06.verisilicon.com> Signed-off-by: Gerd Hoffmann --- ui/vnc.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/ui/vnc.c b/ui/vnc.c index 3ccd33dedc..310a873c21 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -3098,6 +3098,9 @@ static int vnc_refresh_server_surface(VncDisplay *vd) VncState *vs; int has_dirty = 0; pixman_image_t *tmpbuf = NULL; + unsigned long offset; + int x; + uint8_t *guest_ptr, *server_ptr; struct timeval tv = { 0, 0 }; @@ -3106,6 +3109,13 @@ static int vnc_refresh_server_surface(VncDisplay *vd) has_dirty = vnc_update_stats(vd, &tv); } + offset = find_next_bit((unsigned long *) &vd->guest.dirty, + height * VNC_DIRTY_BPL(&vd->guest), 0); + if (offset == height * VNC_DIRTY_BPL(&vd->guest)) { + /* no dirty bits in guest surface */ + return has_dirty; + } + /* * Walk through the guest dirty map. * Check and copy modified bits from guest to server surface. @@ -3130,15 +3140,6 @@ static int vnc_refresh_server_surface(VncDisplay *vd) line_bytes = MIN(server_stride, guest_ll); for (;;) { - int x; - uint8_t *guest_ptr, *server_ptr; - unsigned long offset = find_next_bit((unsigned long *) &vd->guest.dirty, - height * VNC_DIRTY_BPL(&vd->guest), - y * VNC_DIRTY_BPL(&vd->guest)); - if (offset == height * VNC_DIRTY_BPL(&vd->guest)) { - /* no more dirty bits */ - break; - } y = offset / VNC_DIRTY_BPL(&vd->guest); x = offset % VNC_DIRTY_BPL(&vd->guest); @@ -3177,6 +3178,13 @@ static int vnc_refresh_server_surface(VncDisplay *vd) } y++; + offset = find_next_bit((unsigned long *) &vd->guest.dirty, + height * VNC_DIRTY_BPL(&vd->guest), + y * VNC_DIRTY_BPL(&vd->guest)); + if (offset == height * VNC_DIRTY_BPL(&vd->guest)) { + /* no more dirty bits */ + break; + } } qemu_pixman_image_unref(tmpbuf); return has_dirty; From 832061a2fa33b933bf3e080cbc3625ec99bacd30 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Wed, 16 Mar 2022 15:10:53 +0900 Subject: [PATCH 3/6] audio/mixeng: Do not declare unused variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The unused variables when FLOAT_MIXENG is defined caused warnings on Apple clang version 13.1.6 (clang-1316.0.21.2). Signed-off-by: Akihiko Odaki Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220316061053.60587-1-akihiko.odaki@gmail.com> Signed-off-by: Gerd Hoffmann --- audio/mixeng.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/audio/mixeng.c b/audio/mixeng.c index f27deb165b..100a306d6f 100644 --- a/audio/mixeng.c +++ b/audio/mixeng.c @@ -342,13 +342,13 @@ f_sample *mixeng_clip_float[2] = { void audio_sample_to_uint64(const void *samples, int pos, uint64_t *left, uint64_t *right) { - const struct st_sample *sample = samples; - sample += pos; #ifdef FLOAT_MIXENG error_report( "Coreaudio and floating point samples are not supported by replay yet"); abort(); #else + const struct st_sample *sample = samples; + sample += pos; *left = sample->l; *right = sample->r; #endif @@ -357,13 +357,13 @@ void audio_sample_to_uint64(const void *samples, int pos, void audio_sample_from_uint64(void *samples, int pos, uint64_t left, uint64_t right) { - struct st_sample *sample = samples; - sample += pos; #ifdef FLOAT_MIXENG error_report( "Coreaudio and floating point samples are not supported by replay yet"); abort(); #else + struct st_sample *sample = samples; + sample += pos; sample->l = left; sample->r = right; #endif From 5f2011be44b8d17f93680d01d617cd9a96678886 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 17 Mar 2022 09:30:24 +0100 Subject: [PATCH 4/6] hw/display/cirrus_vga: Clean up indentation in pci_cirrus_vga_realize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the code in this function had been indented with 5 spaces instead of 4. Since 4 is our preferred style, remove one space in the bad lines here. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-Id: <20220317083027.16688-2-thuth@redhat.com> Signed-off-by: Gerd Hoffmann --- hw/display/cirrus_vga.c | 55 +++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index fdca6ca659..7da1be3e12 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -2940,27 +2940,28 @@ void cirrus_init_common(CirrusVGAState *s, Object *owner, static void pci_cirrus_vga_realize(PCIDevice *dev, Error **errp) { - PCICirrusVGAState *d = PCI_CIRRUS_VGA(dev); - CirrusVGAState *s = &d->cirrus_vga; - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); - int16_t device_id = pc->device_id; + PCICirrusVGAState *d = PCI_CIRRUS_VGA(dev); + CirrusVGAState *s = &d->cirrus_vga; + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); + int16_t device_id = pc->device_id; - /* follow real hardware, cirrus card emulated has 4 MB video memory. - Also accept 8 MB/16 MB for backward compatibility. */ - if (s->vga.vram_size_mb != 4 && s->vga.vram_size_mb != 8 && - s->vga.vram_size_mb != 16) { - error_setg(errp, "Invalid cirrus_vga ram size '%u'", - s->vga.vram_size_mb); - return; - } - /* setup VGA */ - vga_common_init(&s->vga, OBJECT(dev)); - cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev), - pci_address_space_io(dev)); - s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga); - - /* setup PCI */ + /* + * Follow real hardware, cirrus card emulated has 4 MB video memory. + * Also accept 8 MB/16 MB for backward compatibility. + */ + if (s->vga.vram_size_mb != 4 && s->vga.vram_size_mb != 8 && + s->vga.vram_size_mb != 16) { + error_setg(errp, "Invalid cirrus_vga ram size '%u'", + s->vga.vram_size_mb); + return; + } + /* setup VGA */ + vga_common_init(&s->vga, OBJECT(dev)); + cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev), + pci_address_space_io(dev)); + s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga); + /* setup PCI */ memory_region_init(&s->pci_bar, OBJECT(dev), "cirrus-pci-bar0", 0x2000000); /* XXX: add byte swapping apertures */ @@ -2968,14 +2969,14 @@ static void pci_cirrus_vga_realize(PCIDevice *dev, Error **errp) memory_region_add_subregion(&s->pci_bar, 0x1000000, &s->cirrus_linear_bitblt_io); - /* setup memory space */ - /* memory #0 LFB */ - /* memory #1 memory-mapped I/O */ - /* XXX: s->vga.vram_size must be a power of two */ - pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->pci_bar); - if (device_id == CIRRUS_ID_CLGD5446) { - pci_register_bar(&d->dev, 1, 0, &s->cirrus_mmio_io); - } + /* setup memory space */ + /* memory #0 LFB */ + /* memory #1 memory-mapped I/O */ + /* XXX: s->vga.vram_size must be a power of two */ + pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->pci_bar); + if (device_id == CIRRUS_ID_CLGD5446) { + pci_register_bar(&d->dev, 1, 0, &s->cirrus_mmio_io); + } } static Property pci_vga_cirrus_properties[] = { From 6832deb8ff0807e0b46a8a67f5d2abfa36ca3b47 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 17 Mar 2022 09:30:25 +0100 Subject: [PATCH 5/6] hw/display: Allow vga_common_init() to return errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vga_common_init() function currently cannot report errors to its caller. But in the following patch, we'd need this possibility, so let's change it to take an "Error **" as parameter for this. Signed-off-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220317083027.16688-3-thuth@redhat.com> Signed-off-by: Gerd Hoffmann --- hw/display/ati.c | 4 +++- hw/display/cirrus_vga.c | 4 +++- hw/display/cirrus_vga_isa.c | 4 +++- hw/display/qxl.c | 6 +++++- hw/display/vga-isa.c | 5 ++++- hw/display/vga-mmio.c | 5 ++++- hw/display/vga-pci.c | 8 ++++++-- hw/display/vga.c | 11 +++++++++-- hw/display/vga_int.h | 2 +- hw/display/virtio-vga.c | 4 +++- hw/display/vmware_vga.c | 2 +- 11 files changed, 42 insertions(+), 13 deletions(-) diff --git a/hw/display/ati.c b/hw/display/ati.c index 31f22754dc..6e38e00502 100644 --- a/hw/display/ati.c +++ b/hw/display/ati.c @@ -955,7 +955,9 @@ static void ati_vga_realize(PCIDevice *dev, Error **errp) } /* init vga bits */ - vga_common_init(vga, OBJECT(s)); + if (!vga_common_init(vga, OBJECT(s), errp)) { + return; + } vga_init(vga, OBJECT(s), pci_address_space(dev), pci_address_space_io(dev), true); vga->con = graphic_console_init(DEVICE(s), 0, s->vga.hw_ops, &s->vga); diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index 7da1be3e12..3bb6a58698 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -2956,7 +2956,9 @@ static void pci_cirrus_vga_realize(PCIDevice *dev, Error **errp) return; } /* setup VGA */ - vga_common_init(&s->vga, OBJECT(dev)); + if (!vga_common_init(&s->vga, OBJECT(dev), errp)) { + return; + } cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev), pci_address_space_io(dev)); s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga); diff --git a/hw/display/cirrus_vga_isa.c b/hw/display/cirrus_vga_isa.c index 4f6fb1af3b..96144bd690 100644 --- a/hw/display/cirrus_vga_isa.c +++ b/hw/display/cirrus_vga_isa.c @@ -56,7 +56,9 @@ static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp) return; } s->global_vmstate = true; - vga_common_init(s, OBJECT(dev)); + if (!vga_common_init(s, OBJECT(dev), errp)) { + return; + } cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0, isa_address_space(isadev), isa_address_space_io(isadev)); diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 1f9ad31943..adbdbcaeb6 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -2215,7 +2215,11 @@ static void qxl_realize_primary(PCIDevice *dev, Error **errp) qxl_init_ramsize(qxl); vga->vbe_size = qxl->vgamem_size; vga->vram_size_mb = qxl->vga.vram_size / MiB; - vga_common_init(vga, OBJECT(dev)); + vga_common_init(vga, OBJECT(dev), &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } vga_init(vga, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev), false); portio_list_init(&qxl->vga_port_list, OBJECT(dev), qxl_vga_portio_list, diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c index 90851e730b..46abbc5653 100644 --- a/hw/display/vga-isa.c +++ b/hw/display/vga-isa.c @@ -62,7 +62,10 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp) const MemoryRegionPortio *vga_ports, *vbe_ports; s->global_vmstate = true; - vga_common_init(s, OBJECT(dev)); + if (!vga_common_init(s, OBJECT(dev), errp)) { + return; + } + s->legacy_address_space = isa_address_space(isadev); vga_io_memory = vga_init_io(s, OBJECT(dev), &vga_ports, &vbe_ports); isa_register_portio_list(isadev, &d->portio_vga, diff --git a/hw/display/vga-mmio.c b/hw/display/vga-mmio.c index 4969368081..75dfcedea5 100644 --- a/hw/display/vga-mmio.c +++ b/hw/display/vga-mmio.c @@ -102,7 +102,10 @@ static void vga_mmio_realizefn(DeviceState *dev, Error **errp) s->vga.bank_offset = 0; s->vga.global_vmstate = true; - vga_common_init(&s->vga, OBJECT(dev)); + if (!vga_common_init(&s->vga, OBJECT(dev), errp)) { + return; + } + sysbus_init_mmio(sbd, &s->vga.vram); s->vga.con = graphic_console_init(dev, 0, s->vga.hw_ops, &s->vga); } diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c index 62fb5c38c1..3e5bc259f7 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -239,7 +239,9 @@ static void pci_std_vga_realize(PCIDevice *dev, Error **errp) bool edid = false; /* vga + console init */ - vga_common_init(s, OBJECT(dev)); + if (!vga_common_init(s, OBJECT(dev), errp)) { + return; + } vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev), true); @@ -275,7 +277,9 @@ static void pci_secondary_vga_realize(PCIDevice *dev, Error **errp) bool edid = false; /* vga + console init */ - vga_common_init(s, OBJECT(dev)); + if (!vga_common_init(s, OBJECT(dev), errp)) { + return; + } s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s); /* mmio bar */ diff --git a/hw/display/vga.c b/hw/display/vga.c index 9d1f66af40..ae96023596 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -2168,9 +2168,10 @@ static inline uint32_t uint_clamp(uint32_t val, uint32_t vmin, uint32_t vmax) return val; } -void vga_common_init(VGACommonState *s, Object *obj) +bool vga_common_init(VGACommonState *s, Object *obj, Error **errp) { int i, j, v, b; + Error *local_err = NULL; for(i = 0;i < 256; i++) { v = 0; @@ -2206,7 +2207,11 @@ void vga_common_init(VGACommonState *s, Object *obj) s->is_vbe_vmstate = 1; memory_region_init_ram_nomigrate(&s->vram, obj, "vga.vram", s->vram_size, - &error_fatal); + &local_err); + if (local_err) { + error_propagate(errp, local_err); + return false; + } vmstate_register_ram(&s->vram, s->global_vmstate ? NULL : DEVICE(obj)); xen_register_framebuffer(&s->vram); s->vram_ptr = memory_region_get_ram_ptr(&s->vram); @@ -2237,6 +2242,8 @@ void vga_common_init(VGACommonState *s, Object *obj) s->default_endian_fb = false; #endif vga_dirty_log_start(s); + + return true; } static const MemoryRegionPortio vga_portio_list[] = { diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h index 847e784ca6..305e700014 100644 --- a/hw/display/vga_int.h +++ b/hw/display/vga_int.h @@ -156,7 +156,7 @@ static inline int c6_to_8(int v) return (v << 2) | (b << 1) | b; } -void vga_common_init(VGACommonState *s, Object *obj); +bool vga_common_init(VGACommonState *s, Object *obj, Error **errp); void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space, MemoryRegion *address_space_io, bool init_vga_ports); MemoryRegion *vga_init_io(VGACommonState *s, Object *obj, diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c index 5a2f7a4540..7b55c8d0e7 100644 --- a/hw/display/virtio-vga.c +++ b/hw/display/virtio-vga.c @@ -108,7 +108,9 @@ static void virtio_vga_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp) /* init vga compat bits */ vga->vram_size_mb = 8; - vga_common_init(vga, OBJECT(vpci_dev)); + if (!vga_common_init(vga, OBJECT(vpci_dev), errp)) { + return; + } vga_init(vga, OBJECT(vpci_dev), pci_address_space(&vpci_dev->pci_dev), pci_address_space_io(&vpci_dev->pci_dev), true); pci_register_bar(&vpci_dev->pci_dev, 0, diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 0cc43a1f15..98c83474ad 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -1254,7 +1254,7 @@ static void vmsvga_init(DeviceState *dev, struct vmsvga_state_s *s, &error_fatal); s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram); - vga_common_init(&s->vga, OBJECT(dev)); + vga_common_init(&s->vga, OBJECT(dev), &error_fatal); vga_init(&s->vga, OBJECT(dev), address_space, io, true); vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga); s->new_depth = 32; From 9eb840a20998a97c0ad0f5ced6ebc7e6a88a4dc4 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 17 Mar 2022 09:30:26 +0100 Subject: [PATCH 6/6] hw/display/vga: Report a proper error when adding a 2nd ISA VGA QEMU currently abort()s if the user tries to add a second ISA VGA device, for example: $ ./qemu-system-x86_64 -device isa-vga -device isa-vga RAMBlock "vga.vram" already registered, abort! Aborted (core dumped) $ ./qemu-system-x86_64 -device isa-cirrus-vga -device isa-cirrus-vga RAMBlock "vga.vram" already registered, abort! Aborted (core dumped) $ ./qemu-system-mips64el -M pica61 -device isa-vga RAMBlock "vga.vram" already registered, abort! Aborted (core dumped) Such a crash should never happen just because of giving bad parameters at the command line. Let's return a proper error message instead. (The idea is based on an original patch by Jose R. Ziviani for the isa-vga device, but this now fixes it for the isa-cirrus-vga device, too) Resolves: https://gitlab.com/qemu-project/qemu/-/issues/44 Signed-off-by: Thomas Huth Message-Id: <20220317083027.16688-4-thuth@redhat.com> Signed-off-by: Gerd Hoffmann --- hw/display/vga.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/display/vga.c b/hw/display/vga.c index ae96023596..a7a291fa20 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -2206,6 +2206,12 @@ bool vga_common_init(VGACommonState *s, Object *obj, Error **errp) s->vbe_size_mask = s->vbe_size - 1; s->is_vbe_vmstate = 1; + + if (s->global_vmstate && qemu_ram_block_by_name("vga.vram")) { + error_setg(errp, "Only one global VGA device can be used at a time"); + return false; + } + memory_region_init_ram_nomigrate(&s->vram, obj, "vga.vram", s->vram_size, &local_err); if (local_err) {