diff --git a/0000-libcacard-fix-missing-symbols-in-libcacard.so.patch b/0000-libcacard-fix-missing-symbols-in-libcacard.so.patch deleted file mode 100644 index b6350c3..0000000 --- a/0000-libcacard-fix-missing-symbols-in-libcacard.so.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 94afb78477a5b078449e5d48b38e74aac3fa5ac4 Mon Sep 17 00:00:00 2001 -Message-Id: <94afb78477a5b078449e5d48b38e74aac3fa5ac4.1354903384.git.crobinso@redhat.com> -From: Alon Levy -Date: Wed, 28 Nov 2012 16:38:43 +0200 -Subject: [PATCH] libcacard: fix missing symbols in libcacard.so - ---- - libcacard/Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libcacard/Makefile b/libcacard/Makefile -index c26aac6..49a9729 100644 ---- a/libcacard/Makefile -+++ b/libcacard/Makefile -@@ -7,7 +7,7 @@ libcacard_includedir=$(includedir)/cacard - $(call set-vpath, $(SRC_PATH)) - - # objects linked into a shared library, built with libtool with -fPIC if required --QEMU_OBJS=$(oslib-obj-y) qemu-timer-common.o $(trace-obj-y) $(stub-obj-y) -+QEMU_OBJS=$(oslib-obj-y) qemu-timer-common.o iov.o cutils.o qemu-user.o $(trace-obj-y) $(stub-obj-y) - QEMU_OBJS_LIB=$(patsubst %.o,%.lo,$(QEMU_OBJS)) - - QEMU_CFLAGS+=-I../ --- -1.8.0 - diff --git a/0001-configure-move-vscclient-binary-under-libcacard.patch b/0001-configure-move-vscclient-binary-under-libcacard.patch deleted file mode 100644 index 4feb854..0000000 --- a/0001-configure-move-vscclient-binary-under-libcacard.patch +++ /dev/null @@ -1,96 +0,0 @@ -From df9d09b15cb4b8397bfe984bf3f54dbb5457d446 Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <94afb78477a5b078449e5d48b38e74aac3fa5ac4.1354903384.git.crobinso@redhat.com> -References: <94afb78477a5b078449e5d48b38e74aac3fa5ac4.1354903384.git.crobinso@redhat.com> -From: Alon Levy -Date: Thu, 29 Nov 2012 14:11:19 +0200 -Subject: [PATCH] configure: move vscclient binary under libcacard - -build rule is in top level Makefile like other tools. - -build rule also exists in libcacard for installation purposes. This was -fixed in a better way in 1.3.0-rc2 ---- - Makefile | 4 ++-- - Makefile.objs | 11 ++++++----- - configure | 2 +- - libcacard/Makefile | 6 +++++- - 4 files changed, 14 insertions(+), 9 deletions(-) - -diff --git a/Makefile b/Makefile -index 9ecbcbb..c2d34a9 100644 ---- a/Makefile -+++ b/Makefile -@@ -197,8 +197,8 @@ qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y) libqemustub.a - - qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o - --vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) libcacard/vscclient.o libqemustub.a -- $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS)," LINK $@") -+libcacard/vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) iov.o cutils.o qemu-user.o libcacard/vscclient.o libqemustub.a -+libcacard/vscclient$(EXESUF): LIBS += $(libcacard_libs) - - fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y) - fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap -diff --git a/Makefile.objs b/Makefile.objs -index 3c7abca..140d592 100644 ---- a/Makefile.objs -+++ b/Makefile.objs -@@ -211,11 +211,12 @@ $(trace-obj-y): $(GENERATED_HEADERS) - ###################################################################### - # smartcard - --libcacard-y += libcacard/cac.o libcacard/event.o --libcacard-y += libcacard/vcard.o libcacard/vreader.o --libcacard-y += libcacard/vcard_emul_nss.o --libcacard-y += libcacard/vcard_emul_type.o --libcacard-y += libcacard/card_7816.o -+libcacard-base-y += cac.o event.o -+libcacard-base-y += vcard.o vreader.o -+libcacard-base-y += vcard_emul_nss.o -+libcacard-base-y += vcard_emul_type.o -+libcacard-base-y += card_7816.o -+libcacard-y = $(addprefix libcacard/,$(libcacard-base-y)) - - common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y) - -diff --git a/configure b/configure -index 994f731..7498e3f 100755 ---- a/configure -+++ b/configure -@@ -3136,7 +3136,7 @@ if test "$softmmu" = yes ; then - fi - fi - if test "$smartcard_nss" = "yes" ; then -- tools="vscclient\$(EXESUF) $tools" -+ tools="libcacard/vscclient\$(EXESUF) $tools" - fi - fi - -diff --git a/libcacard/Makefile b/libcacard/Makefile -index 49a9729..750713a 100644 ---- a/libcacard/Makefile -+++ b/libcacard/Makefile -@@ -47,6 +47,10 @@ libcacard.pc: $(libcacard_srcpath)/libcacard.pc.in - < $(libcacard_srcpath)/libcacard.pc.in > libcacard.pc,\ - " GEN $@") - -+VSCCLIENT_QEMU_OBJS=$(addprefix ../,$(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o iov.o cutils.o qemu-user.o) -+vscclient$(EXESUF): $(VSCCLIENT_QEMU_OBJS) $(libcacard-base-y) vscclient.o -+vscclient$(EXESUF): LIBS += $(libcacard_libs) -+ - .PHONY: install-libcacard - - install-libcacard: libcacard.pc libcacard.la vscclient -@@ -54,7 +58,7 @@ install-libcacard: libcacard.pc libcacard.la vscclient - $(INSTALL_DIR) "$(DESTDIR)$(libdir)/pkgconfig" - $(INSTALL_DIR) "$(DESTDIR)$(libcacard_includedir)" - $(INSTALL_DIR) "$(DESTDIR)$(bindir)" -- $(LIBTOOL) --mode=install $(INSTALL_PROG) vscclient "$(DESTDIR)$(bindir)" -+ $(LIBTOOL) --mode=install $(INSTALL_PROG) vscclient$(EXESUF) "$(DESTDIR)$(bindir)" - $(LIBTOOL) --mode=install $(INSTALL_DATA) libcacard.la "$(DESTDIR)$(libdir)" - $(LIBTOOL) --mode=install $(INSTALL_DATA) libcacard.pc "$(DESTDIR)$(libdir)/pkgconfig" - for inc in *.h; do \ --- -1.8.0 - diff --git a/0001-libcacard-fix-missing-symbols-in-libcacard.so.patch b/0001-libcacard-fix-missing-symbols-in-libcacard.so.patch new file mode 100644 index 0000000..27e4360 --- /dev/null +++ b/0001-libcacard-fix-missing-symbols-in-libcacard.so.patch @@ -0,0 +1,25 @@ +From 94afb78477a5b078449e5d48b38e74aac3fa5ac4 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Wed, 28 Nov 2012 16:38:43 +0200 +Subject: [PATCH] libcacard: fix missing symbols in libcacard.so + +--- + libcacard/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libcacard/Makefile b/libcacard/Makefile +index c26aac6..49a9729 100644 +--- a/libcacard/Makefile ++++ b/libcacard/Makefile +@@ -7,7 +7,7 @@ libcacard_includedir=$(includedir)/cacard + $(call set-vpath, $(SRC_PATH)) + + # objects linked into a shared library, built with libtool with -fPIC if required +-QEMU_OBJS=$(oslib-obj-y) qemu-timer-common.o $(trace-obj-y) $(stub-obj-y) ++QEMU_OBJS=$(oslib-obj-y) qemu-timer-common.o iov.o cutils.o qemu-user.o $(trace-obj-y) $(stub-obj-y) + QEMU_OBJS_LIB=$(patsubst %.o,%.lo,$(QEMU_OBJS)) + + QEMU_CFLAGS+=-I../ +-- +1.8.1 + diff --git a/0002-Fix-migration-from-qemu-kvm-1.2.patch b/0002-Fix-migration-from-qemu-kvm-1.2.patch deleted file mode 100644 index a04a862..0000000 --- a/0002-Fix-migration-from-qemu-kvm-1.2.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 633ff09ae5702676d0f33cba80db45ff5bdbde0f Mon Sep 17 00:00:00 2001 -Message-Id: <633ff09ae5702676d0f33cba80db45ff5bdbde0f.1354903384.git.crobinso@redhat.com> -In-Reply-To: <94afb78477a5b078449e5d48b38e74aac3fa5ac4.1354903384.git.crobinso@redhat.com> -References: <94afb78477a5b078449e5d48b38e74aac3fa5ac4.1354903384.git.crobinso@redhat.com> -From: Cole Robinson -Date: Fri, 7 Dec 2012 12:32:41 -0500 -Subject: [PATCH] Fix migration from qemu-kvm 1.2 - -As suggested by Marcelo ---- - hw/acpi_piix4.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c -index 519269a..66adc88 100644 ---- a/hw/acpi_piix4.c -+++ b/hw/acpi_piix4.c -@@ -310,8 +310,8 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id) - */ - static const VMStateDescription vmstate_acpi = { - .name = "piix4_pm", -- .version_id = 3, -- .minimum_version_id = 3, -+ .version_id = 2, -+ .minimum_version_id = 2, - .minimum_version_id_old = 1, - .load_state_old = acpi_load_old, - .post_load = vmstate_acpi_post_load, --- -1.8.0 - diff --git a/0002-configure-move-vscclient-binary-under-libcacard.patch b/0002-configure-move-vscclient-binary-under-libcacard.patch new file mode 100644 index 0000000..bca69a6 --- /dev/null +++ b/0002-configure-move-vscclient-binary-under-libcacard.patch @@ -0,0 +1,93 @@ +From df9d09b15cb4b8397bfe984bf3f54dbb5457d446 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Thu, 29 Nov 2012 14:11:19 +0200 +Subject: [PATCH] configure: move vscclient binary under libcacard + +build rule is in top level Makefile like other tools. + +build rule also exists in libcacard for installation purposes. This was +fixed in a better way in 1.3.0-rc2 +--- + Makefile | 4 ++-- + Makefile.objs | 11 ++++++----- + configure | 2 +- + libcacard/Makefile | 6 +++++- + 4 files changed, 14 insertions(+), 9 deletions(-) + +diff --git a/Makefile b/Makefile +index 9ecbcbb..c2d34a9 100644 +--- a/Makefile ++++ b/Makefile +@@ -197,8 +197,8 @@ qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y) libqemustub.a + + qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o + +-vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) libcacard/vscclient.o libqemustub.a +- $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS)," LINK $@") ++libcacard/vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) iov.o cutils.o qemu-user.o libcacard/vscclient.o libqemustub.a ++libcacard/vscclient$(EXESUF): LIBS += $(libcacard_libs) + + fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y) + fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap +diff --git a/Makefile.objs b/Makefile.objs +index 3c7abca..140d592 100644 +--- a/Makefile.objs ++++ b/Makefile.objs +@@ -211,11 +211,12 @@ $(trace-obj-y): $(GENERATED_HEADERS) + ###################################################################### + # smartcard + +-libcacard-y += libcacard/cac.o libcacard/event.o +-libcacard-y += libcacard/vcard.o libcacard/vreader.o +-libcacard-y += libcacard/vcard_emul_nss.o +-libcacard-y += libcacard/vcard_emul_type.o +-libcacard-y += libcacard/card_7816.o ++libcacard-base-y += cac.o event.o ++libcacard-base-y += vcard.o vreader.o ++libcacard-base-y += vcard_emul_nss.o ++libcacard-base-y += vcard_emul_type.o ++libcacard-base-y += card_7816.o ++libcacard-y = $(addprefix libcacard/,$(libcacard-base-y)) + + common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y) + +diff --git a/configure b/configure +index 994f731..7498e3f 100755 +--- a/configure ++++ b/configure +@@ -3136,7 +3136,7 @@ if test "$softmmu" = yes ; then + fi + fi + if test "$smartcard_nss" = "yes" ; then +- tools="vscclient\$(EXESUF) $tools" ++ tools="libcacard/vscclient\$(EXESUF) $tools" + fi + fi + +diff --git a/libcacard/Makefile b/libcacard/Makefile +index 49a9729..750713a 100644 +--- a/libcacard/Makefile ++++ b/libcacard/Makefile +@@ -47,6 +47,10 @@ libcacard.pc: $(libcacard_srcpath)/libcacard.pc.in + < $(libcacard_srcpath)/libcacard.pc.in > libcacard.pc,\ + " GEN $@") + ++VSCCLIENT_QEMU_OBJS=$(addprefix ../,$(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o iov.o cutils.o qemu-user.o) ++vscclient$(EXESUF): $(VSCCLIENT_QEMU_OBJS) $(libcacard-base-y) vscclient.o ++vscclient$(EXESUF): LIBS += $(libcacard_libs) ++ + .PHONY: install-libcacard + + install-libcacard: libcacard.pc libcacard.la vscclient +@@ -54,7 +58,7 @@ install-libcacard: libcacard.pc libcacard.la vscclient + $(INSTALL_DIR) "$(DESTDIR)$(libdir)/pkgconfig" + $(INSTALL_DIR) "$(DESTDIR)$(libcacard_includedir)" + $(INSTALL_DIR) "$(DESTDIR)$(bindir)" +- $(LIBTOOL) --mode=install $(INSTALL_PROG) vscclient "$(DESTDIR)$(bindir)" ++ $(LIBTOOL) --mode=install $(INSTALL_PROG) vscclient$(EXESUF) "$(DESTDIR)$(bindir)" + $(LIBTOOL) --mode=install $(INSTALL_DATA) libcacard.la "$(DESTDIR)$(libdir)" + $(LIBTOOL) --mode=install $(INSTALL_DATA) libcacard.pc "$(DESTDIR)$(libdir)/pkgconfig" + for inc in *.h; do \ +-- +1.8.1 + diff --git a/0003-rtc-test-skip-year-2038-overflow-check-in-case-time_.patch b/0003-rtc-test-skip-year-2038-overflow-check-in-case-time_.patch new file mode 100644 index 0000000..7f9a1c5 --- /dev/null +++ b/0003-rtc-test-skip-year-2038-overflow-check-in-case-time_.patch @@ -0,0 +1,29 @@ +From 43eb809a0f98b644cf4a2dd6a257185ad781346c Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 7 Jan 2013 15:11:52 +0100 +Subject: [PATCH] rtc-test: skip year-2038 overflow check in case time_t is + 32bit only + +Signed-off-by: Gerd Hoffmann +--- + tests/rtc-test.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tests/rtc-test.c b/tests/rtc-test.c +index 02edbf5..e7123ca 100644 +--- a/tests/rtc-test.c ++++ b/tests/rtc-test.c +@@ -201,6 +201,10 @@ static void set_year_20xx(void) + g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11); + g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20); + ++ if (sizeof(time_t) == 4) { ++ return; ++ } ++ + /* Set a date in 2080 to ensure there is no year-2038 overflow. */ + cmos_write(RTC_REG_A, 0x76); + cmos_write(RTC_YEAR, 0x80); +-- +1.8.1 + diff --git a/0004-Fix-migration-compat-with-qemu-kvm.patch b/0004-Fix-migration-compat-with-qemu-kvm.patch new file mode 100644 index 0000000..57852a4 --- /dev/null +++ b/0004-Fix-migration-compat-with-qemu-kvm.patch @@ -0,0 +1,70 @@ +From 99c9360e120aa7098952564af5bda76834498442 Mon Sep 17 00:00:00 2001 +From: Cole Robinson +Date: Mon, 14 Jan 2013 21:49:21 -0500 +Subject: [PATCH] Fix migration compat with qemu-kvm + +Outlined here: +https://lists.gnu.org/archive/html/qemu-devel/2013-01/msg02340.html +https://lists.gnu.org/archive/html/qemu-devel/2013-01/msg02540.html +--- + hw/acpi_piix4.c | 2 +- + hw/cirrus_vga.c | 2 +- + hw/pc_piix.c | 16 ---------------- + 3 files changed, 2 insertions(+), 18 deletions(-) + +diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c +index 519269a..785e756 100644 +--- a/hw/acpi_piix4.c ++++ b/hw/acpi_piix4.c +@@ -311,7 +311,7 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id) + static const VMStateDescription vmstate_acpi = { + .name = "piix4_pm", + .version_id = 3, +- .minimum_version_id = 3, ++ .minimum_version_id = 2, + .minimum_version_id_old = 1, + .load_state_old = acpi_load_old, + .post_load = vmstate_acpi_post_load, +diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c +index 9bef96e..8c94428 100644 +--- a/hw/cirrus_vga.c ++++ b/hw/cirrus_vga.c +@@ -2975,7 +2975,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) + + static Property pci_vga_cirrus_properties[] = { + DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState, +- cirrus_vga.vga.vram_size_mb, 8), ++ cirrus_vga.vga.vram_size_mb, 16), + DEFINE_PROP_END_OF_LIST(), + }; + +diff --git a/hw/pc_piix.c b/hw/pc_piix.c +index aa3e7f4..ea37ef2 100644 +--- a/hw/pc_piix.c ++++ b/hw/pc_piix.c +@@ -339,22 +339,6 @@ static QEMUMachine pc_machine_v1_2 = { + .property = "param_change",\ + .value = "off",\ + },{\ +- .driver = "VGA",\ +- .property = "vgamem_mb",\ +- .value = stringify(8),\ +- },{\ +- .driver = "vmware-svga",\ +- .property = "vgamem_mb",\ +- .value = stringify(8),\ +- },{\ +- .driver = "qxl-vga",\ +- .property = "vgamem_mb",\ +- .value = stringify(8),\ +- },{\ +- .driver = "qxl",\ +- .property = "vgamem_mb",\ +- .value = stringify(8),\ +- },{\ + .driver = "virtio-blk-pci",\ + .property = "config-wce",\ + .value = "off",\ +-- +1.8.1 + diff --git a/0100-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch b/0100-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch deleted file mode 100644 index 06e63fb..0000000 --- a/0100-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 9f0944a25bc1094fa7a74ac9df14e184e2c5c82d Mon Sep 17 00:00:00 2001 -Message-Id: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Amit Shah -Date: Mon, 21 Mar 2011 21:57:47 +0100 -Subject: [PATCH] char: Split out tcp socket close code in a separate function - -Signed-off-by: Amit Shah -Signed-off-by: Cole Robinson ---- - qemu-char.c | 25 ++++++++++++++++--------- - 1 file changed, 16 insertions(+), 9 deletions(-) - -diff --git a/qemu-char.c b/qemu-char.c -index 242b799..77776dc 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -2146,6 +2146,21 @@ typedef struct { - - static void tcp_chr_accept(void *opaque); - -+static void tcp_closed(void *opaque) -+{ -+ CharDriverState *chr = opaque; -+ TCPCharDriver *s = chr->opaque; -+ -+ s->connected = 0; -+ if (s->listen_fd >= 0) { -+ qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr); -+ } -+ qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); -+ closesocket(s->fd); -+ s->fd = -1; -+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED); -+} -+ - static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - { - TCPCharDriver *s = chr->opaque; -@@ -2304,15 +2319,7 @@ static void tcp_chr_read(void *opaque) - len = s->max_size; - size = tcp_chr_recv(chr, (void *)buf, len); - if (size == 0) { -- /* connection closed */ -- s->connected = 0; -- if (s->listen_fd >= 0) { -- qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr); -- } -- qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); -- closesocket(s->fd); -- s->fd = -1; -- qemu_chr_be_event(chr, CHR_EVENT_CLOSED); -+ tcp_closed(chr); - } else if (size > 0) { - if (s->do_telnetopt) - tcp_chr_process_IAC_bytes(chr, s, buf, &size); --- -1.8.0 - diff --git a/0101-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch b/0101-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch deleted file mode 100644 index 1b2953a..0000000 --- a/0101-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch +++ /dev/null @@ -1,1046 +0,0 @@ -From 501ffec04b2b5104ef854624027f0cd769d5d314 Mon Sep 17 00:00:00 2001 -Message-Id: <501ffec04b2b5104ef854624027f0cd769d5d314.1354903384.git.crobinso@redhat.com> -In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Amit Shah -Date: Mon, 21 Mar 2011 20:31:45 +0100 -Subject: [PATCH] char: Add a QemuChrHandlers struct to initialise chardev - handlers - -Instead of passing each handler in the qemu_add_handlers() function, -create a struct of handlers that can be passed to the function instead. - -Signed-off-by: Amit Shah -Signed-off-by: Cole Robinson ---- - backends/rng-egd.c | 12 +++++++++--- - gdbstub.c | 9 +++++++-- - hw/cadence_uart.c | 9 +++++++-- - hw/ccid-card-passthru.c | 11 +++++++---- - hw/debugcon.c | 2 +- - hw/escc.c | 9 +++++++-- - hw/etraxfs_ser.c | 13 +++++++++---- - hw/exynos4210_uart.c | 9 +++++++-- - hw/grlib_apbuart.c | 12 +++++++----- - hw/imx_serial.c | 9 +++++++-- - hw/ivshmem.c | 28 ++++++++++++++++++++++------ - hw/lm32_juart.c | 8 +++++++- - hw/lm32_uart.c | 8 +++++++- - hw/mcf_uart.c | 9 +++++++-- - hw/milkymist-uart.c | 8 +++++++- - hw/pl011.c | 9 +++++++-- - hw/pxa2xx.c | 13 +++++++++---- - hw/qdev-properties.c | 2 +- - hw/s390x/sclpconsole.c | 9 +++++++-- - hw/serial.c | 11 ++++++++--- - hw/sh_serial.c | 12 +++++++++--- - hw/spapr_vty.c | 8 ++++++-- - hw/strongarm.c | 12 +++++++----- - hw/usb/dev-serial.c | 11 ++++++++--- - hw/usb/redirect.c | 9 +++++++-- - hw/virtio-console.c | 9 +++++++-- - hw/xen_console.c | 16 +++++++++++----- - hw/xilinx_uartlite.c | 11 +++++++++-- - monitor.c | 18 ++++++++++++++---- - net/slirp.c | 8 ++++++-- - qemu-char.c | 32 ++++++++++++++++++++++---------- - qemu-char.h | 13 +++++++++---- - qtest.c | 9 ++++++++- - 33 files changed, 273 insertions(+), 95 deletions(-) - -diff --git a/backends/rng-egd.c b/backends/rng-egd.c -index ad84737..30194be 100644 ---- a/backends/rng-egd.c -+++ b/backends/rng-egd.c -@@ -133,6 +133,13 @@ static void rng_egd_cancel_requests(RngBackend *b) - rng_egd_free_requests(s); - } - -+static const QemuChrHandlers rng_egd_handlers = { -+ .fd_can_read = rng_egd_chr_can_read, -+ .fd_read = rng_egd_chr_read, -+ .fd_event = NULL, -+}; -+ -+ - static void rng_egd_opened(RngBackend *b, Error **errp) - { - RngEgd *s = RNG_EGD(b); -@@ -150,8 +157,7 @@ static void rng_egd_opened(RngBackend *b, Error **errp) - } - - /* FIXME we should resubmit pending requests when the CDS reconnects. */ -- qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read, -- NULL, s); -+ qemu_chr_add_handlers(s->chr, &rng_egd_handlers, s); - } - - static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp) -@@ -190,7 +196,7 @@ static void rng_egd_finalize(Object *obj) - RngEgd *s = RNG_EGD(obj); - - if (s->chr) { -- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL); -+ qemu_chr_add_handlers(s->chr, NULL, NULL); - } - - g_free(s->chr_name); -diff --git a/gdbstub.c b/gdbstub.c -index d02ec75..5d93d20 100644 ---- a/gdbstub.c -+++ b/gdbstub.c -@@ -2973,6 +2973,12 @@ static void gdb_sigterm_handler(int signal) - } - #endif - -+static const QemuChrHandlers gdb_handlers = { -+ .fd_can_read = gdb_chr_can_receive, -+ .fd_read = gdb_chr_receive, -+ .fd_event = gdb_chr_event, -+}; -+ - int gdbserver_start(const char *device) - { - GDBState *s; -@@ -3002,8 +3008,7 @@ int gdbserver_start(const char *device) - if (!chr) - return -1; - -- qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, -- gdb_chr_event, NULL); -+ qemu_chr_add_handlers(chr, &gdb_handlers, NULL); - } - - s = gdbserver_state; -diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c -index 686e617..36ad620 100644 ---- a/hw/cadence_uart.c -+++ b/hw/cadence_uart.c -@@ -438,6 +438,12 @@ static void cadence_uart_reset(UartState *s) - s->rx_wpos = 0; - } - -+static const QemuChrHandlers cadence_uart_handlers = { -+ .fd_can_read = uart_can_receive, -+ .fd_read = uart_receive, -+ .fd_event = uart_event, -+}; -+ - static int cadence_uart_init(SysBusDevice *dev) - { - UartState *s = FROM_SYSBUS(UartState, dev); -@@ -459,8 +465,7 @@ static int cadence_uart_init(SysBusDevice *dev) - cadence_uart_reset(s); - - if (s->chr) { -- qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive, -- uart_event, s); -+ qemu_chr_add_handlers(s->chr, &cadence_uart_handlers, s); - } - - return 0; -diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c -index bd6c777..fb32107 100644 ---- a/hw/ccid-card-passthru.c -+++ b/hw/ccid-card-passthru.c -@@ -274,6 +274,12 @@ static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len) - return card->atr; - } - -+static const QemuChrHandlers passthru_handlers = { -+ .fd_can_read = ccid_card_vscard_can_read, -+ .fd_read = ccid_card_vscard_read, -+ .fd_event = ccid_card_vscard_event, -+}; -+ - static int passthru_initfn(CCIDCardState *base) - { - PassthruState *card = DO_UPCAST(PassthruState, base, base); -@@ -282,10 +288,7 @@ static int passthru_initfn(CCIDCardState *base) - card->vscard_in_hdr = 0; - if (card->cs) { - DPRINTF(card, D_INFO, "initing chardev\n"); -- qemu_chr_add_handlers(card->cs, -- ccid_card_vscard_can_read, -- ccid_card_vscard_read, -- ccid_card_vscard_event, card); -+ qemu_chr_add_handlers(card->cs, &passthru_handlers, card); - ccid_card_vscard_send_init(card); - } else { - error_report("missing chardev"); -diff --git a/hw/debugcon.c b/hw/debugcon.c -index 14ab326..7887fd2 100644 ---- a/hw/debugcon.c -+++ b/hw/debugcon.c -@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s) - exit(1); - } - -- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s); -+ qemu_chr_add_handlers(s->chr, NULL, s); - } - - static int debugcon_isa_initfn(ISADevice *dev) -diff --git a/hw/escc.c b/hw/escc.c -index a356613..3f26f45 100644 ---- a/hw/escc.c -+++ b/hw/escc.c -@@ -867,6 +867,12 @@ void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq, - sysbus_mmio_map(s, 0, base); - } - -+static const QemuChrHandlers serial_handlers = { -+ .fd_can_read = serial_can_receive, -+ .fd_read = serial_receive1, -+ .fd_event = serial_event, -+}; -+ - static int escc_init1(SysBusDevice *dev) - { - SerialState *s = FROM_SYSBUS(SerialState, dev); -@@ -879,8 +885,7 @@ static int escc_init1(SysBusDevice *dev) - s->chn[i].chn = 1 - i; - s->chn[i].clock = s->frequency / 2; - if (s->chn[i].chr) { -- qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive, -- serial_receive1, serial_event, &s->chn[i]); -+ qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]); - } - } - s->chn[0].otherchn = &s->chn[1]; -diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c -index ee0d72b..64552cc 100644 ---- a/hw/etraxfs_ser.c -+++ b/hw/etraxfs_ser.c -@@ -208,6 +208,12 @@ static void etraxfs_ser_reset(DeviceState *d) - - } - -+static const QemuChrHandlers serial_handlers = { -+ .fd_can_read = serial_can_receive, -+ .fd_read = serial_receive, -+ .fd_event = serial_event, -+}; -+ - static int etraxfs_ser_init(SysBusDevice *dev) - { - struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev); -@@ -217,10 +223,9 @@ static int etraxfs_ser_init(SysBusDevice *dev) - sysbus_init_mmio(dev, &s->mmio); - - s->chr = qemu_char_get_next_serial(); -- if (s->chr) -- qemu_chr_add_handlers(s->chr, -- serial_can_receive, serial_receive, -- serial_event, s); -+ if (s->chr) { -+ qemu_chr_add_handlers(s->chr, &serial_handlers, s); -+ } - return 0; - } - -diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c -index 20dcd9f..f2949aa 100644 ---- a/hw/exynos4210_uart.c -+++ b/hw/exynos4210_uart.c -@@ -625,6 +625,12 @@ DeviceState *exynos4210_uart_create(hwaddr addr, - return dev; - } - -+static const QemuChrHandlers exynos4210_handlers = { -+ .fd_can_read = exynos4210_uart_can_receive, -+ .fd_read = exynos4210_uart_receive, -+ .fd_event = exynos4210_uart_event, -+}; -+ - static int exynos4210_uart_init(SysBusDevice *dev) - { - Exynos4210UartState *s = FROM_SYSBUS(Exynos4210UartState, dev); -@@ -636,8 +642,7 @@ static int exynos4210_uart_init(SysBusDevice *dev) - - sysbus_init_irq(dev, &s->irq); - -- qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive, -- exynos4210_uart_receive, exynos4210_uart_event, s); -+ qemu_chr_add_handlers(s->chr, &exynos4210_handlers, s); - - return 0; - } -diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c -index 0865764..fb0e703 100644 ---- a/hw/grlib_apbuart.c -+++ b/hw/grlib_apbuart.c -@@ -222,15 +222,17 @@ static const MemoryRegionOps grlib_apbuart_ops = { - .endianness = DEVICE_NATIVE_ENDIAN, - }; - -+static const QemuChrHandlers grlib_handlers = { -+ .fd_can_read = grlib_apbuart_can_receive, -+ .fd_read = grlib_apbuart_receive, -+ .fd_event = grlib_apbuart_event, -+}; -+ - static int grlib_apbuart_init(SysBusDevice *dev) - { - UART *uart = FROM_SYSBUS(typeof(*uart), dev); - -- qemu_chr_add_handlers(uart->chr, -- grlib_apbuart_can_receive, -- grlib_apbuart_receive, -- grlib_apbuart_event, -- uart); -+ qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart); - - sysbus_init_irq(dev, &uart->irq); - -diff --git a/hw/imx_serial.c b/hw/imx_serial.c -index dcd125f..5347ec8 100644 ---- a/hw/imx_serial.c -+++ b/hw/imx_serial.c -@@ -381,6 +381,12 @@ static const struct MemoryRegionOps imx_serial_ops = { - .endianness = DEVICE_NATIVE_ENDIAN, - }; - -+static const QemuChrHandlers imx_handlers = { -+ .fd_can_read = imx_can_receive, -+ .fd_read = imx_receive, -+ .fd_event = imx_event, -+}; -+ - static int imx_serial_init(SysBusDevice *dev) - { - IMXSerialState *s = FROM_SYSBUS(IMXSerialState, dev); -@@ -391,8 +397,7 @@ static int imx_serial_init(SysBusDevice *dev) - sysbus_init_irq(dev, &s->irq); - - if (s->chr) { -- qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive, -- imx_event, s); -+ qemu_chr_add_handlers(s->chr, &imx_handlers, s); - } else { - DPRINTF("No char dev for uart at 0x%lx\n", - (unsigned long)s->iomem.ram_addr); -diff --git a/hw/ivshmem.c b/hw/ivshmem.c -index f6dbb21..0e56a97 100644 ---- a/hw/ivshmem.c -+++ b/hw/ivshmem.c -@@ -274,6 +274,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) { - msix_notify(pdev, entry->vector); - } - -+static const QemuChrHandlers ivshmem_handlers = { -+ .fd_can_read = ivshmem_can_receive, -+ .fd_read = ivshmem_receive, -+ .fd_event = ivshmem_event, -+}; -+ -+static const QemuChrHandlers ivshmem_msi_handlers = { -+ .fd_can_read = ivshmem_can_receive, -+ .fd_read = fake_irqfd, -+ .fd_event = ivshmem_event, -+}; -+ - static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *n, - int vector) - { -@@ -294,11 +306,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier * - s->eventfd_table[vector].pdev = &s->dev; - s->eventfd_table[vector].vector = vector; - -- qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd, -- ivshmem_event, &s->eventfd_table[vector]); -+ qemu_chr_add_handlers(chr, &ivshmem_msi_handlers, -+ &s->eventfd_table[vector]); - } else { -- qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive, -- ivshmem_event, s); -+ qemu_chr_add_handlers(chr, &ivshmem_handlers, s); - } - - return chr; -@@ -632,6 +643,12 @@ static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address, - msix_write_config(pci_dev, address, val, len); - } - -+static const QemuChrHandlers ivshmem_server_handlers = { -+ .fd_can_read = ivshmem_can_receive, -+ .fd_read = ivshmem_read, -+ .fd_event = ivshmem_event, -+}; -+ - static int pci_ivshmem_init(PCIDevice *dev) - { - IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev); -@@ -722,8 +739,7 @@ static int pci_ivshmem_init(PCIDevice *dev) - - s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *)); - -- qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read, -- ivshmem_event, s); -+ qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s); - } else { - /* just map the file immediately, we're not using a server */ - int fd; -diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c -index f07ed39..d4daeb8 100644 ---- a/hw/lm32_juart.c -+++ b/hw/lm32_juart.c -@@ -110,13 +110,19 @@ static void juart_reset(DeviceState *d) - s->jrx = 0; - } - -+static const QemuChrHandlers juart_handlers = { -+ .fd_can_read = juart_can_rx, -+ .fd_read = juart_rx, -+ .fd_event = juart_event, -+}; -+ - static int lm32_juart_init(SysBusDevice *dev) - { - LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev); - - s->chr = qemu_char_get_next_serial(); - if (s->chr) { -- qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s); -+ qemu_chr_add_handlers(s->chr, &juart_handlers, s); - } - - return 0; -diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c -index adb9287..e581bea 100644 ---- a/hw/lm32_uart.c -+++ b/hw/lm32_uart.c -@@ -243,6 +243,12 @@ static void uart_reset(DeviceState *d) - s->regs[R_LSR] = LSR_THRE | LSR_TEMT; - } - -+static const QemuChrHandlers uart_handlers = { -+ .fd_can_read = uart_can_rx, -+ .fd_read = uart_rx, -+ .fd_event = uart_event, -+}; -+ - static int lm32_uart_init(SysBusDevice *dev) - { - LM32UartState *s = FROM_SYSBUS(typeof(*s), dev); -@@ -254,7 +260,7 @@ static int lm32_uart_init(SysBusDevice *dev) - - s->chr = qemu_char_get_next_serial(); - if (s->chr) { -- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); -+ qemu_chr_add_handlers(s->chr, &uart_handlers, s); - } - - return 0; -diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c -index d1655f8..8ead254 100644 ---- a/hw/mcf_uart.c -+++ b/hw/mcf_uart.c -@@ -272,6 +272,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size) - mcf_uart_push_byte(s, buf[0]); - } - -+static const QemuChrHandlers mcf_uart_handlers = { -+ .fd_can_read = mcf_uart_can_receive, -+ .fd_read = mcf_uart_receive, -+ .fd_event = mcf_uart_event, -+}; -+ - void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) - { - mcf_uart_state *s; -@@ -280,8 +286,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) - s->chr = chr; - s->irq = irq; - if (chr) { -- qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive, -- mcf_uart_event, s); -+ qemu_chr_add_handlers(chr, &mcf_uart_handlers, s); - } - mcf_uart_reset(s); - return s; -diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c -index aefa8c7..0c924f2 100644 ---- a/hw/milkymist-uart.c -+++ b/hw/milkymist-uart.c -@@ -189,6 +189,12 @@ static void milkymist_uart_reset(DeviceState *d) - s->regs[R_STAT] = STAT_THRE; - } - -+static const QemuChrHandlers uart_handlers = { -+ .fd_can_read = uart_can_rx, -+ .fd_read = uart_rx, -+ .fd_event = uart_event, -+}; -+ - static int milkymist_uart_init(SysBusDevice *dev) - { - MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev); -@@ -201,7 +207,7 @@ static int milkymist_uart_init(SysBusDevice *dev) - - s->chr = qemu_char_get_next_serial(); - if (s->chr) { -- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); -+ qemu_chr_add_handlers(s->chr, &uart_handlers, s); - } - - return 0; -diff --git a/hw/pl011.c b/hw/pl011.c -index 1f7ce2f..7f44c55 100644 ---- a/hw/pl011.c -+++ b/hw/pl011.c -@@ -261,6 +261,12 @@ static const VMStateDescription vmstate_pl011 = { - } - }; - -+static const QemuChrHandlers pl011_handlers = { -+ .fd_can_read = pl011_can_receive, -+ .fd_read = pl011_receive, -+ .fd_event = pl011_event, -+}; -+ - static int pl011_init(SysBusDevice *dev, const unsigned char *id) - { - pl011_state *s = FROM_SYSBUS(pl011_state, dev); -@@ -276,8 +282,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id) - s->cr = 0x300; - s->flags = 0x90; - if (s->chr) { -- qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive, -- pl011_event, s); -+ qemu_chr_add_handlers(s->chr, &pl011_handlers, s); - } - vmstate_register(&dev->qdev, -1, &vmstate_pl011, s); - return 0; -diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c -index e616979..f9ca062 100644 ---- a/hw/pxa2xx.c -+++ b/hw/pxa2xx.c -@@ -1962,6 +1962,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id) - return 0; - } - -+static const QemuChrHandlers pxa2xx_handlers = { -+ .fd_can_read = pxa2xx_fir_is_empty, -+ .fd_read = pxa2xx_fir_rx, -+ .fd_event = pxa2xx_fir_event, -+}; -+ - static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem, - hwaddr base, - qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma, -@@ -1980,10 +1986,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem, - memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000); - memory_region_add_subregion(sysmem, base, &s->iomem); - -- if (chr) -- qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty, -- pxa2xx_fir_rx, pxa2xx_fir_event, s); -- -+ if (chr) { -+ qemu_chr_add_handlers(chr, &pxa2xx_handlers, s); -+ } - register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save, - pxa2xx_fir_load, s); - -diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c -index 81d901c..9e2b893 100644 ---- a/hw/qdev-properties.c -+++ b/hw/qdev-properties.c -@@ -550,7 +550,7 @@ static void release_chr(Object *obj, const char *name, void *opaque) - CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); - - if (*ptr) { -- qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL); -+ qemu_chr_add_handlers(*ptr, NULL, NULL); - } - } - -diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c -index 0ec5623..b3d1d6b 100644 ---- a/hw/s390x/sclpconsole.c -+++ b/hw/s390x/sclpconsole.c -@@ -240,6 +240,12 @@ static void trigger_ascii_console_data(void *env, int n, int level) - sclp_service_interrupt(0); - } - -+static const QemuChrHandlers sclp_chr_handlers = { -+ .fd_can_read = chr_can_read, -+ .fd_read = chr_read, -+ .fd_event = chr_event, -+}; -+ - /* qemu object creation and initialization functions */ - - /* tell character layer our call-back functions */ -@@ -256,8 +262,7 @@ static int console_init(SCLPEvent *event) - console_available = true; - event->event_type = SCLP_EVENT_ASCII_CONSOLE_DATA; - if (scon->chr) { -- qemu_chr_add_handlers(scon->chr, chr_can_read, -- chr_read, chr_event, scon); -+ qemu_chr_add_handlers(scon->chr, &sclp_chr_handlers, scon); - } - scon->irq_read_vt220 = *qemu_allocate_irqs(trigger_ascii_console_data, - NULL, 1); -diff --git a/hw/serial.c b/hw/serial.c -index 60283ea..9134d01 100644 ---- a/hw/serial.c -+++ b/hw/serial.c -@@ -676,6 +676,12 @@ static void serial_reset(void *opaque) - qemu_irq_lower(s->irq); - } - -+static const QemuChrHandlers serial_handlers = { -+ .fd_can_read = serial_can_receive1, -+ .fd_read = serial_receive1, -+ .fd_event = serial_event, -+}; -+ - void serial_init_core(SerialState *s) - { - if (!s->chr) { -@@ -690,13 +696,12 @@ void serial_init_core(SerialState *s) - - qemu_register_reset(serial_reset, s); - -- qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1, -- serial_event, s); -+ qemu_chr_add_handlers(s->chr, &serial_handlers, s); - } - - void serial_exit_core(SerialState *s) - { -- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL); -+ qemu_chr_add_handlers(s->chr, NULL, NULL); - qemu_unregister_reset(serial_reset, s); - } - -diff --git a/hw/sh_serial.c b/hw/sh_serial.c -index 9da5d08..260185d 100644 ---- a/hw/sh_serial.c -+++ b/hw/sh_serial.c -@@ -352,6 +352,12 @@ static const MemoryRegionOps sh_serial_ops = { - .endianness = DEVICE_NATIVE_ENDIAN, - }; - -+static const QemuChrHandlers sh_serial_handlers = { -+ .fd_can_read = sh_serial_can_receive1, -+ .fd_read = sh_serial_receive1, -+ .fd_event = sh_serial_event, -+}; -+ - void sh_serial_init(MemoryRegion *sysmem, - hwaddr base, int feat, - uint32_t freq, CharDriverState *chr, -@@ -396,9 +402,9 @@ void sh_serial_init(MemoryRegion *sysmem, - - s->chr = chr; - -- if (chr) -- qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1, -- sh_serial_event, s); -+ if (chr) { -+ qemu_chr_add_handlers(chr, &sh_serial_handlers, s); -+ } - - s->eri = eri_source; - s->rxi = rxi_source; -diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c -index 14f862f..9fbe7dd 100644 ---- a/hw/spapr_vty.c -+++ b/hw/spapr_vty.c -@@ -54,6 +54,11 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len) - qemu_chr_fe_write(dev->chardev, buf, len); - } - -+static const QemuChrHandlers vty_handlers = { -+ .fd_can_read = vty_can_receive, -+ .fd_read = vty_receive, -+}; -+ - static int spapr_vty_init(VIOsPAPRDevice *sdev) - { - VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev; -@@ -63,8 +68,7 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev) - exit(1); - } - -- qemu_chr_add_handlers(dev->chardev, vty_can_receive, -- vty_receive, NULL, dev); -+ qemu_chr_add_handlers(dev->chardev, &vty_handlers, dev); - - return 0; - } -diff --git a/hw/strongarm.c b/hw/strongarm.c -index 4385515..3567218 100644 ---- a/hw/strongarm.c -+++ b/hw/strongarm.c -@@ -1199,6 +1199,12 @@ static const MemoryRegionOps strongarm_uart_ops = { - .endianness = DEVICE_NATIVE_ENDIAN, - }; - -+static const QemuChrHandlers strongarm_uart_handlers = { -+ .fd_can_read = strongarm_uart_can_receive, -+ .fd_read = strongarm_uart_receive, -+ .fd_event = strongarm_uart_event, -+}; -+ - static int strongarm_uart_init(SysBusDevice *dev) - { - StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev); -@@ -1211,11 +1217,7 @@ static int strongarm_uart_init(SysBusDevice *dev) - s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s); - - if (s->chr) { -- qemu_chr_add_handlers(s->chr, -- strongarm_uart_can_receive, -- strongarm_uart_receive, -- strongarm_uart_event, -- s); -+ qemu_chr_add_handlers(s->chr, &strongarm_uart_handlers, s); - } - - return 0; -diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c -index 99b19df..7307ad2 100644 ---- a/hw/usb/dev-serial.c -+++ b/hw/usb/dev-serial.c -@@ -414,7 +414,7 @@ static void usb_serial_handle_destroy(USBDevice *dev) - { - USBSerialState *s = (USBSerialState *)dev; - -- qemu_chr_add_handlers(s->cs, NULL, NULL, NULL, NULL); -+ qemu_chr_add_handlers(s->cs, NULL, NULL); - } - - static int usb_serial_can_read(void *opaque) -@@ -478,6 +478,12 @@ static void usb_serial_event(void *opaque, int event) - } - } - -+static const QemuChrHandlers usb_serial_handlers = { -+ .fd_can_read = usb_serial_can_read, -+ .fd_read = usb_serial_read, -+ .fd_event = usb_serial_event, -+}; -+ - static int usb_serial_initfn(USBDevice *dev) - { - USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev); -@@ -491,8 +497,7 @@ static int usb_serial_initfn(USBDevice *dev) - return -1; - } - -- qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read, -- usb_serial_event, s); -+ qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s); - usb_serial_handle_reset(dev); - - if (s->cs->opened && !dev->attached) { -diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c -index 490c90f..c921d2d 100644 ---- a/hw/usb/redirect.c -+++ b/hw/usb/redirect.c -@@ -1037,6 +1037,12 @@ static void usbredir_chardev_event(void *opaque, int event) - } - } - -+static const QemuChrHandlers usbredir_chr_handlers = { -+ .fd_can_read = usbredir_chardev_can_read, -+ .fd_read = usbredir_chardev_read, -+ .fd_event = usbredir_chardev_event, -+}; -+ - /* - * init + destroy - */ -@@ -1088,8 +1094,7 @@ static int usbredir_initfn(USBDevice *udev) - - /* Let the backend know we are ready */ - qemu_chr_fe_open(dev->cs); -- qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read, -- usbredir_chardev_read, usbredir_chardev_event, dev); -+ qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev); - - qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev); - add_boot_device_path(dev->bootindex, &udev->qdev, NULL); -diff --git a/hw/virtio-console.c b/hw/virtio-console.c -index cffee3d..066590c 100644 ---- a/hw/virtio-console.c -+++ b/hw/virtio-console.c -@@ -106,6 +106,12 @@ static void chr_event(void *opaque, int event) - } - } - -+static const QemuChrHandlers chr_handlers = { -+ .fd_can_read = chr_can_read, -+ .fd_read = chr_read, -+ .fd_event = chr_event, -+}; -+ - static int virtconsole_initfn(VirtIOSerialPort *port) - { - VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); -@@ -117,8 +123,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port) - } - - if (vcon->chr) { -- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event, -- vcon); -+ qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon); - } - - return 0; -diff --git a/hw/xen_console.c b/hw/xen_console.c -index 9426d73..e9fcadc 100644 ---- a/hw/xen_console.c -+++ b/hw/xen_console.c -@@ -211,6 +211,11 @@ out: - return ret; - } - -+static const QemuChrHandlers xencons_handlers = { -+ .fd_can_read = xencons_can_receive, -+ .fd_read = xencons_receive, -+}; -+ - static int con_initialise(struct XenDevice *xendev) - { - struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); -@@ -231,9 +236,9 @@ static int con_initialise(struct XenDevice *xendev) - return -1; - - xen_be_bind_evtchn(&con->xendev); -- if (con->chr) -- qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive, -- NULL, con); -+ if (con->chr) { -+ qemu_chr_add_handlers(con->chr, &xencons_handlers, con); -+ } - - xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n", - con->ring_ref, -@@ -250,8 +255,9 @@ static void con_disconnect(struct XenDevice *xendev) - if (!xendev->dev) { - return; - } -- if (con->chr) -- qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL); -+ if (con->chr) { -+ qemu_chr_add_handlers(con->chr, NULL, NULL); -+ } - xen_be_unbind_evtchn(&con->xendev); - - if (con->sring) { -diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c -index d20fc41..6605fb1 100644 ---- a/hw/xilinx_uartlite.c -+++ b/hw/xilinx_uartlite.c -@@ -195,6 +195,12 @@ static void uart_event(void *opaque, int event) - - } - -+static const QemuChrHandlers uart_handlers = { -+ .fd_can_read = uart_can_rx, -+ .fd_read = uart_rx, -+ .fd_event = uart_event, -+}; -+ - static int xilinx_uartlite_init(SysBusDevice *dev) - { - struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev); -@@ -207,8 +213,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev) - sysbus_init_mmio(dev, &s->mmio); - - s->chr = qemu_char_get_next_serial(); -- if (s->chr) -- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); -+ if (s->chr) { -+ qemu_chr_add_handlers(s->chr, &uart_handlers, s); -+ } - return 0; - } - -diff --git a/monitor.c b/monitor.c -index c0e32d6..ce0c90a 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -4685,6 +4685,18 @@ static void sortcmdlist(void) - * End: - */ - -+static const QemuChrHandlers monitor_handlers = { -+ .fd_can_read = monitor_can_read, -+ .fd_read = monitor_read, -+ .fd_event = monitor_event, -+}; -+ -+static const QemuChrHandlers monitor_control_handlers = { -+ .fd_can_read = monitor_can_read, -+ .fd_read = monitor_control_read, -+ .fd_event = monitor_control_event, -+}; -+ - void monitor_init(CharDriverState *chr, int flags) - { - static int is_first_init = 1; -@@ -4707,14 +4719,12 @@ void monitor_init(CharDriverState *chr, int flags) - if (monitor_ctrl_mode(mon)) { - mon->mc = g_malloc0(sizeof(MonitorControl)); - /* Control mode requires special handlers */ -- qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read, -- monitor_control_event, mon); -+ qemu_chr_add_handlers(chr, &monitor_control_handlers, mon); - qemu_chr_fe_set_echo(chr, true); - - json_message_parser_init(&mon->mc->parser, handle_qmp_command); - } else { -- qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, -- monitor_event, mon); -+ qemu_chr_add_handlers(chr, &monitor_handlers, mon); - } - - QLIST_INSERT_HEAD(&mon_list, mon, entry); -diff --git a/net/slirp.c b/net/slirp.c -index afb52c3..07ae92f 100644 ---- a/net/slirp.c -+++ b/net/slirp.c -@@ -594,6 +594,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size) - slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size); - } - -+static const QemuChrHandlers guestfwd_handlers = { -+ .fd_can_read = guestfwd_can_read, -+ .fd_read = guestfwd_read, -+}; -+ - static int slirp_guestfwd(SlirpState *s, const char *config_str, - int legacy_format) - { -@@ -659,8 +664,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, - fwd->port = port; - fwd->slirp = s->slirp; - -- qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read, -- NULL, fwd); -+ qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd); - } - return 0; - -diff --git a/qemu-char.c b/qemu-char.c -index 77776dc..97247fb 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -193,19 +193,26 @@ void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...) - va_end(ap); - } - -+static const QemuChrHandlers null_handlers = { -+ /* All handlers are initialised to NULL */ -+}; -+ - void qemu_chr_add_handlers(CharDriverState *s, -- IOCanReadHandler *fd_can_read, -- IOReadHandler *fd_read, -- IOEventHandler *fd_event, -- void *opaque) -+ const QemuChrHandlers *handlers, void *opaque) - { -- if (!opaque && !fd_can_read && !fd_read && !fd_event) { -+ if (!s) { -+ return; -+ } -+ if (!opaque && !handlers) { - /* chr driver being released. */ - ++s->avail_connections; - } -- s->chr_can_read = fd_can_read; -- s->chr_read = fd_read; -- s->chr_event = fd_event; -+ if (!handlers) { -+ handlers = &null_handlers; -+ } -+ s->chr_can_read = handlers->fd_can_read; -+ s->chr_read = handlers->fd_read; -+ s->chr_event = handlers->fd_event; - s->handler_opaque = opaque; - if (s->chr_update_read_handler) - s->chr_update_read_handler(s); -@@ -443,6 +450,12 @@ static void mux_chr_event(void *opaque, int event) - mux_chr_send_event(d, i, event); - } - -+static const QemuChrHandlers mux_chr_handlers = { -+ .fd_can_read = mux_chr_can_read, -+ .fd_read = mux_chr_read, -+ .fd_event = mux_chr_event, -+}; -+ - static void mux_chr_update_read_handler(CharDriverState *chr) - { - MuxDriver *d = chr->opaque; -@@ -457,8 +470,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr) - d->chr_event[d->mux_cnt] = chr->chr_event; - /* Fix up the real driver with mux routines */ - if (d->mux_cnt == 0) { -- qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read, -- mux_chr_event, chr); -+ qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr); - } - if (d->focus != -1) { - mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); -diff --git a/qemu-char.h b/qemu-char.h -index a121e04..ff206cb 100644 ---- a/qemu-char.h -+++ b/qemu-char.h -@@ -223,10 +223,15 @@ void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len); - */ - void qemu_chr_be_event(CharDriverState *s, int event); - --void qemu_chr_add_handlers(CharDriverState *s, -- IOCanReadHandler *fd_can_read, -- IOReadHandler *fd_read, -- IOEventHandler *fd_event, -+ -+typedef struct QemuChrHandlers { -+ IOCanReadHandler *fd_can_read; -+ IOReadHandler *fd_read; -+ IOHandler *fd_write_unblocked; -+ IOEventHandler *fd_event; -+} QemuChrHandlers; -+ -+void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers, - void *opaque); - - void qemu_chr_generic_open(CharDriverState *s); -diff --git a/qtest.c b/qtest.c -index fbfab4e..4ab5b69 100644 ---- a/qtest.c -+++ b/qtest.c -@@ -416,6 +416,13 @@ static void qtest_event(void *opaque, int event) - } - } - -+static const QemuChrHandlers test_handlers = { -+ .fd_can_read = qtest_can_read, -+ .fd_read = qtest_read, -+ .fd_event = qtest_event, -+}; -+ -+ - int qtest_init(void) - { - CharDriverState *chr; -@@ -425,7 +432,7 @@ int qtest_init(void) - configure_icount("0"); - chr = qemu_chr_new("qtest", qtest_chrdev, NULL); - -- qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr); -+ qemu_chr_add_handlers(chr, &test_handlers, chr); - qemu_chr_fe_set_echo(chr, true); - - inbuf = g_string_new(""); --- -1.8.0 - diff --git a/0101-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch b/0101-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch new file mode 100644 index 0000000..df59f85 --- /dev/null +++ b/0101-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch @@ -0,0 +1,57 @@ +From 973df60b495a87a9cd3b6909d08c148f5fd93691 Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Mon, 21 Mar 2011 21:57:47 +0100 +Subject: [PATCH] char: Split out tcp socket close code in a separate function + +Signed-off-by: Amit Shah +Signed-off-by: Cole Robinson +--- + qemu-char.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index 242b799..77776dc 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -2146,6 +2146,21 @@ typedef struct { + + static void tcp_chr_accept(void *opaque); + ++static void tcp_closed(void *opaque) ++{ ++ CharDriverState *chr = opaque; ++ TCPCharDriver *s = chr->opaque; ++ ++ s->connected = 0; ++ if (s->listen_fd >= 0) { ++ qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr); ++ } ++ qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); ++ closesocket(s->fd); ++ s->fd = -1; ++ qemu_chr_be_event(chr, CHR_EVENT_CLOSED); ++} ++ + static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) + { + TCPCharDriver *s = chr->opaque; +@@ -2304,15 +2319,7 @@ static void tcp_chr_read(void *opaque) + len = s->max_size; + size = tcp_chr_recv(chr, (void *)buf, len); + if (size == 0) { +- /* connection closed */ +- s->connected = 0; +- if (s->listen_fd >= 0) { +- qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr); +- } +- qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); +- closesocket(s->fd); +- s->fd = -1; +- qemu_chr_be_event(chr, CHR_EVENT_CLOSED); ++ tcp_closed(chr); + } else if (size > 0) { + if (s->do_telnetopt) + tcp_chr_process_IAC_bytes(chr, s, buf, &size); +-- +1.8.1 + diff --git a/0102-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch b/0102-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch new file mode 100644 index 0000000..0684934 --- /dev/null +++ b/0102-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch @@ -0,0 +1,1043 @@ +From 687d91769e40878f3b8ebb9bdd8ee256a40c97cd Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Mon, 21 Mar 2011 20:31:45 +0100 +Subject: [PATCH] char: Add a QemuChrHandlers struct to initialise chardev + handlers + +Instead of passing each handler in the qemu_add_handlers() function, +create a struct of handlers that can be passed to the function instead. + +Signed-off-by: Amit Shah +Signed-off-by: Cole Robinson +--- + backends/rng-egd.c | 12 +++++++++--- + gdbstub.c | 9 +++++++-- + hw/cadence_uart.c | 9 +++++++-- + hw/ccid-card-passthru.c | 11 +++++++---- + hw/debugcon.c | 2 +- + hw/escc.c | 9 +++++++-- + hw/etraxfs_ser.c | 13 +++++++++---- + hw/exynos4210_uart.c | 9 +++++++-- + hw/grlib_apbuart.c | 12 +++++++----- + hw/imx_serial.c | 9 +++++++-- + hw/ivshmem.c | 28 ++++++++++++++++++++++------ + hw/lm32_juart.c | 8 +++++++- + hw/lm32_uart.c | 8 +++++++- + hw/mcf_uart.c | 9 +++++++-- + hw/milkymist-uart.c | 8 +++++++- + hw/pl011.c | 9 +++++++-- + hw/pxa2xx.c | 13 +++++++++---- + hw/qdev-properties.c | 2 +- + hw/s390x/sclpconsole.c | 9 +++++++-- + hw/serial.c | 11 ++++++++--- + hw/sh_serial.c | 12 +++++++++--- + hw/spapr_vty.c | 8 ++++++-- + hw/strongarm.c | 12 +++++++----- + hw/usb/dev-serial.c | 11 ++++++++--- + hw/usb/redirect.c | 9 +++++++-- + hw/virtio-console.c | 9 +++++++-- + hw/xen_console.c | 16 +++++++++++----- + hw/xilinx_uartlite.c | 11 +++++++++-- + monitor.c | 18 ++++++++++++++---- + net/slirp.c | 8 ++++++-- + qemu-char.c | 32 ++++++++++++++++++++++---------- + qemu-char.h | 13 +++++++++---- + qtest.c | 9 ++++++++- + 33 files changed, 273 insertions(+), 95 deletions(-) + +diff --git a/backends/rng-egd.c b/backends/rng-egd.c +index ad84737..30194be 100644 +--- a/backends/rng-egd.c ++++ b/backends/rng-egd.c +@@ -133,6 +133,13 @@ static void rng_egd_cancel_requests(RngBackend *b) + rng_egd_free_requests(s); + } + ++static const QemuChrHandlers rng_egd_handlers = { ++ .fd_can_read = rng_egd_chr_can_read, ++ .fd_read = rng_egd_chr_read, ++ .fd_event = NULL, ++}; ++ ++ + static void rng_egd_opened(RngBackend *b, Error **errp) + { + RngEgd *s = RNG_EGD(b); +@@ -150,8 +157,7 @@ static void rng_egd_opened(RngBackend *b, Error **errp) + } + + /* FIXME we should resubmit pending requests when the CDS reconnects. */ +- qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read, +- NULL, s); ++ qemu_chr_add_handlers(s->chr, &rng_egd_handlers, s); + } + + static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp) +@@ -190,7 +196,7 @@ static void rng_egd_finalize(Object *obj) + RngEgd *s = RNG_EGD(obj); + + if (s->chr) { +- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL); ++ qemu_chr_add_handlers(s->chr, NULL, NULL); + } + + g_free(s->chr_name); +diff --git a/gdbstub.c b/gdbstub.c +index d02ec75..5d93d20 100644 +--- a/gdbstub.c ++++ b/gdbstub.c +@@ -2973,6 +2973,12 @@ static void gdb_sigterm_handler(int signal) + } + #endif + ++static const QemuChrHandlers gdb_handlers = { ++ .fd_can_read = gdb_chr_can_receive, ++ .fd_read = gdb_chr_receive, ++ .fd_event = gdb_chr_event, ++}; ++ + int gdbserver_start(const char *device) + { + GDBState *s; +@@ -3002,8 +3008,7 @@ int gdbserver_start(const char *device) + if (!chr) + return -1; + +- qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, +- gdb_chr_event, NULL); ++ qemu_chr_add_handlers(chr, &gdb_handlers, NULL); + } + + s = gdbserver_state; +diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c +index 686e617..36ad620 100644 +--- a/hw/cadence_uart.c ++++ b/hw/cadence_uart.c +@@ -438,6 +438,12 @@ static void cadence_uart_reset(UartState *s) + s->rx_wpos = 0; + } + ++static const QemuChrHandlers cadence_uart_handlers = { ++ .fd_can_read = uart_can_receive, ++ .fd_read = uart_receive, ++ .fd_event = uart_event, ++}; ++ + static int cadence_uart_init(SysBusDevice *dev) + { + UartState *s = FROM_SYSBUS(UartState, dev); +@@ -459,8 +465,7 @@ static int cadence_uart_init(SysBusDevice *dev) + cadence_uart_reset(s); + + if (s->chr) { +- qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive, +- uart_event, s); ++ qemu_chr_add_handlers(s->chr, &cadence_uart_handlers, s); + } + + return 0; +diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c +index bd6c777..fb32107 100644 +--- a/hw/ccid-card-passthru.c ++++ b/hw/ccid-card-passthru.c +@@ -274,6 +274,12 @@ static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len) + return card->atr; + } + ++static const QemuChrHandlers passthru_handlers = { ++ .fd_can_read = ccid_card_vscard_can_read, ++ .fd_read = ccid_card_vscard_read, ++ .fd_event = ccid_card_vscard_event, ++}; ++ + static int passthru_initfn(CCIDCardState *base) + { + PassthruState *card = DO_UPCAST(PassthruState, base, base); +@@ -282,10 +288,7 @@ static int passthru_initfn(CCIDCardState *base) + card->vscard_in_hdr = 0; + if (card->cs) { + DPRINTF(card, D_INFO, "initing chardev\n"); +- qemu_chr_add_handlers(card->cs, +- ccid_card_vscard_can_read, +- ccid_card_vscard_read, +- ccid_card_vscard_event, card); ++ qemu_chr_add_handlers(card->cs, &passthru_handlers, card); + ccid_card_vscard_send_init(card); + } else { + error_report("missing chardev"); +diff --git a/hw/debugcon.c b/hw/debugcon.c +index 14ab326..7887fd2 100644 +--- a/hw/debugcon.c ++++ b/hw/debugcon.c +@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s) + exit(1); + } + +- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s); ++ qemu_chr_add_handlers(s->chr, NULL, s); + } + + static int debugcon_isa_initfn(ISADevice *dev) +diff --git a/hw/escc.c b/hw/escc.c +index a356613..3f26f45 100644 +--- a/hw/escc.c ++++ b/hw/escc.c +@@ -867,6 +867,12 @@ void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq, + sysbus_mmio_map(s, 0, base); + } + ++static const QemuChrHandlers serial_handlers = { ++ .fd_can_read = serial_can_receive, ++ .fd_read = serial_receive1, ++ .fd_event = serial_event, ++}; ++ + static int escc_init1(SysBusDevice *dev) + { + SerialState *s = FROM_SYSBUS(SerialState, dev); +@@ -879,8 +885,7 @@ static int escc_init1(SysBusDevice *dev) + s->chn[i].chn = 1 - i; + s->chn[i].clock = s->frequency / 2; + if (s->chn[i].chr) { +- qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive, +- serial_receive1, serial_event, &s->chn[i]); ++ qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]); + } + } + s->chn[0].otherchn = &s->chn[1]; +diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c +index ee0d72b..64552cc 100644 +--- a/hw/etraxfs_ser.c ++++ b/hw/etraxfs_ser.c +@@ -208,6 +208,12 @@ static void etraxfs_ser_reset(DeviceState *d) + + } + ++static const QemuChrHandlers serial_handlers = { ++ .fd_can_read = serial_can_receive, ++ .fd_read = serial_receive, ++ .fd_event = serial_event, ++}; ++ + static int etraxfs_ser_init(SysBusDevice *dev) + { + struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev); +@@ -217,10 +223,9 @@ static int etraxfs_ser_init(SysBusDevice *dev) + sysbus_init_mmio(dev, &s->mmio); + + s->chr = qemu_char_get_next_serial(); +- if (s->chr) +- qemu_chr_add_handlers(s->chr, +- serial_can_receive, serial_receive, +- serial_event, s); ++ if (s->chr) { ++ qemu_chr_add_handlers(s->chr, &serial_handlers, s); ++ } + return 0; + } + +diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c +index 20dcd9f..f2949aa 100644 +--- a/hw/exynos4210_uart.c ++++ b/hw/exynos4210_uart.c +@@ -625,6 +625,12 @@ DeviceState *exynos4210_uart_create(hwaddr addr, + return dev; + } + ++static const QemuChrHandlers exynos4210_handlers = { ++ .fd_can_read = exynos4210_uart_can_receive, ++ .fd_read = exynos4210_uart_receive, ++ .fd_event = exynos4210_uart_event, ++}; ++ + static int exynos4210_uart_init(SysBusDevice *dev) + { + Exynos4210UartState *s = FROM_SYSBUS(Exynos4210UartState, dev); +@@ -636,8 +642,7 @@ static int exynos4210_uart_init(SysBusDevice *dev) + + sysbus_init_irq(dev, &s->irq); + +- qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive, +- exynos4210_uart_receive, exynos4210_uart_event, s); ++ qemu_chr_add_handlers(s->chr, &exynos4210_handlers, s); + + return 0; + } +diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c +index 0865764..fb0e703 100644 +--- a/hw/grlib_apbuart.c ++++ b/hw/grlib_apbuart.c +@@ -222,15 +222,17 @@ static const MemoryRegionOps grlib_apbuart_ops = { + .endianness = DEVICE_NATIVE_ENDIAN, + }; + ++static const QemuChrHandlers grlib_handlers = { ++ .fd_can_read = grlib_apbuart_can_receive, ++ .fd_read = grlib_apbuart_receive, ++ .fd_event = grlib_apbuart_event, ++}; ++ + static int grlib_apbuart_init(SysBusDevice *dev) + { + UART *uart = FROM_SYSBUS(typeof(*uart), dev); + +- qemu_chr_add_handlers(uart->chr, +- grlib_apbuart_can_receive, +- grlib_apbuart_receive, +- grlib_apbuart_event, +- uart); ++ qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart); + + sysbus_init_irq(dev, &uart->irq); + +diff --git a/hw/imx_serial.c b/hw/imx_serial.c +index dcd125f..5347ec8 100644 +--- a/hw/imx_serial.c ++++ b/hw/imx_serial.c +@@ -381,6 +381,12 @@ static const struct MemoryRegionOps imx_serial_ops = { + .endianness = DEVICE_NATIVE_ENDIAN, + }; + ++static const QemuChrHandlers imx_handlers = { ++ .fd_can_read = imx_can_receive, ++ .fd_read = imx_receive, ++ .fd_event = imx_event, ++}; ++ + static int imx_serial_init(SysBusDevice *dev) + { + IMXSerialState *s = FROM_SYSBUS(IMXSerialState, dev); +@@ -391,8 +397,7 @@ static int imx_serial_init(SysBusDevice *dev) + sysbus_init_irq(dev, &s->irq); + + if (s->chr) { +- qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive, +- imx_event, s); ++ qemu_chr_add_handlers(s->chr, &imx_handlers, s); + } else { + DPRINTF("No char dev for uart at 0x%lx\n", + (unsigned long)s->iomem.ram_addr); +diff --git a/hw/ivshmem.c b/hw/ivshmem.c +index f6dbb21..0e56a97 100644 +--- a/hw/ivshmem.c ++++ b/hw/ivshmem.c +@@ -274,6 +274,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) { + msix_notify(pdev, entry->vector); + } + ++static const QemuChrHandlers ivshmem_handlers = { ++ .fd_can_read = ivshmem_can_receive, ++ .fd_read = ivshmem_receive, ++ .fd_event = ivshmem_event, ++}; ++ ++static const QemuChrHandlers ivshmem_msi_handlers = { ++ .fd_can_read = ivshmem_can_receive, ++ .fd_read = fake_irqfd, ++ .fd_event = ivshmem_event, ++}; ++ + static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *n, + int vector) + { +@@ -294,11 +306,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier * + s->eventfd_table[vector].pdev = &s->dev; + s->eventfd_table[vector].vector = vector; + +- qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd, +- ivshmem_event, &s->eventfd_table[vector]); ++ qemu_chr_add_handlers(chr, &ivshmem_msi_handlers, ++ &s->eventfd_table[vector]); + } else { +- qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive, +- ivshmem_event, s); ++ qemu_chr_add_handlers(chr, &ivshmem_handlers, s); + } + + return chr; +@@ -632,6 +643,12 @@ static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address, + msix_write_config(pci_dev, address, val, len); + } + ++static const QemuChrHandlers ivshmem_server_handlers = { ++ .fd_can_read = ivshmem_can_receive, ++ .fd_read = ivshmem_read, ++ .fd_event = ivshmem_event, ++}; ++ + static int pci_ivshmem_init(PCIDevice *dev) + { + IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev); +@@ -722,8 +739,7 @@ static int pci_ivshmem_init(PCIDevice *dev) + + s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *)); + +- qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read, +- ivshmem_event, s); ++ qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s); + } else { + /* just map the file immediately, we're not using a server */ + int fd; +diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c +index f07ed39..d4daeb8 100644 +--- a/hw/lm32_juart.c ++++ b/hw/lm32_juart.c +@@ -110,13 +110,19 @@ static void juart_reset(DeviceState *d) + s->jrx = 0; + } + ++static const QemuChrHandlers juart_handlers = { ++ .fd_can_read = juart_can_rx, ++ .fd_read = juart_rx, ++ .fd_event = juart_event, ++}; ++ + static int lm32_juart_init(SysBusDevice *dev) + { + LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev); + + s->chr = qemu_char_get_next_serial(); + if (s->chr) { +- qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s); ++ qemu_chr_add_handlers(s->chr, &juart_handlers, s); + } + + return 0; +diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c +index adb9287..e581bea 100644 +--- a/hw/lm32_uart.c ++++ b/hw/lm32_uart.c +@@ -243,6 +243,12 @@ static void uart_reset(DeviceState *d) + s->regs[R_LSR] = LSR_THRE | LSR_TEMT; + } + ++static const QemuChrHandlers uart_handlers = { ++ .fd_can_read = uart_can_rx, ++ .fd_read = uart_rx, ++ .fd_event = uart_event, ++}; ++ + static int lm32_uart_init(SysBusDevice *dev) + { + LM32UartState *s = FROM_SYSBUS(typeof(*s), dev); +@@ -254,7 +260,7 @@ static int lm32_uart_init(SysBusDevice *dev) + + s->chr = qemu_char_get_next_serial(); + if (s->chr) { +- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); ++ qemu_chr_add_handlers(s->chr, &uart_handlers, s); + } + + return 0; +diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c +index d1655f8..8ead254 100644 +--- a/hw/mcf_uart.c ++++ b/hw/mcf_uart.c +@@ -272,6 +272,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size) + mcf_uart_push_byte(s, buf[0]); + } + ++static const QemuChrHandlers mcf_uart_handlers = { ++ .fd_can_read = mcf_uart_can_receive, ++ .fd_read = mcf_uart_receive, ++ .fd_event = mcf_uart_event, ++}; ++ + void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) + { + mcf_uart_state *s; +@@ -280,8 +286,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) + s->chr = chr; + s->irq = irq; + if (chr) { +- qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive, +- mcf_uart_event, s); ++ qemu_chr_add_handlers(chr, &mcf_uart_handlers, s); + } + mcf_uart_reset(s); + return s; +diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c +index aefa8c7..0c924f2 100644 +--- a/hw/milkymist-uart.c ++++ b/hw/milkymist-uart.c +@@ -189,6 +189,12 @@ static void milkymist_uart_reset(DeviceState *d) + s->regs[R_STAT] = STAT_THRE; + } + ++static const QemuChrHandlers uart_handlers = { ++ .fd_can_read = uart_can_rx, ++ .fd_read = uart_rx, ++ .fd_event = uart_event, ++}; ++ + static int milkymist_uart_init(SysBusDevice *dev) + { + MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev); +@@ -201,7 +207,7 @@ static int milkymist_uart_init(SysBusDevice *dev) + + s->chr = qemu_char_get_next_serial(); + if (s->chr) { +- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); ++ qemu_chr_add_handlers(s->chr, &uart_handlers, s); + } + + return 0; +diff --git a/hw/pl011.c b/hw/pl011.c +index 1f7ce2f..7f44c55 100644 +--- a/hw/pl011.c ++++ b/hw/pl011.c +@@ -261,6 +261,12 @@ static const VMStateDescription vmstate_pl011 = { + } + }; + ++static const QemuChrHandlers pl011_handlers = { ++ .fd_can_read = pl011_can_receive, ++ .fd_read = pl011_receive, ++ .fd_event = pl011_event, ++}; ++ + static int pl011_init(SysBusDevice *dev, const unsigned char *id) + { + pl011_state *s = FROM_SYSBUS(pl011_state, dev); +@@ -276,8 +282,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id) + s->cr = 0x300; + s->flags = 0x90; + if (s->chr) { +- qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive, +- pl011_event, s); ++ qemu_chr_add_handlers(s->chr, &pl011_handlers, s); + } + vmstate_register(&dev->qdev, -1, &vmstate_pl011, s); + return 0; +diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c +index e616979..f9ca062 100644 +--- a/hw/pxa2xx.c ++++ b/hw/pxa2xx.c +@@ -1962,6 +1962,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id) + return 0; + } + ++static const QemuChrHandlers pxa2xx_handlers = { ++ .fd_can_read = pxa2xx_fir_is_empty, ++ .fd_read = pxa2xx_fir_rx, ++ .fd_event = pxa2xx_fir_event, ++}; ++ + static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem, + hwaddr base, + qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma, +@@ -1980,10 +1986,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem, + memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000); + memory_region_add_subregion(sysmem, base, &s->iomem); + +- if (chr) +- qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty, +- pxa2xx_fir_rx, pxa2xx_fir_event, s); +- ++ if (chr) { ++ qemu_chr_add_handlers(chr, &pxa2xx_handlers, s); ++ } + register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save, + pxa2xx_fir_load, s); + +diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c +index 81d901c..9e2b893 100644 +--- a/hw/qdev-properties.c ++++ b/hw/qdev-properties.c +@@ -550,7 +550,7 @@ static void release_chr(Object *obj, const char *name, void *opaque) + CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr) { +- qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL); ++ qemu_chr_add_handlers(*ptr, NULL, NULL); + } + } + +diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c +index 0ec5623..b3d1d6b 100644 +--- a/hw/s390x/sclpconsole.c ++++ b/hw/s390x/sclpconsole.c +@@ -240,6 +240,12 @@ static void trigger_ascii_console_data(void *env, int n, int level) + sclp_service_interrupt(0); + } + ++static const QemuChrHandlers sclp_chr_handlers = { ++ .fd_can_read = chr_can_read, ++ .fd_read = chr_read, ++ .fd_event = chr_event, ++}; ++ + /* qemu object creation and initialization functions */ + + /* tell character layer our call-back functions */ +@@ -256,8 +262,7 @@ static int console_init(SCLPEvent *event) + console_available = true; + event->event_type = SCLP_EVENT_ASCII_CONSOLE_DATA; + if (scon->chr) { +- qemu_chr_add_handlers(scon->chr, chr_can_read, +- chr_read, chr_event, scon); ++ qemu_chr_add_handlers(scon->chr, &sclp_chr_handlers, scon); + } + scon->irq_read_vt220 = *qemu_allocate_irqs(trigger_ascii_console_data, + NULL, 1); +diff --git a/hw/serial.c b/hw/serial.c +index 60283ea..9134d01 100644 +--- a/hw/serial.c ++++ b/hw/serial.c +@@ -676,6 +676,12 @@ static void serial_reset(void *opaque) + qemu_irq_lower(s->irq); + } + ++static const QemuChrHandlers serial_handlers = { ++ .fd_can_read = serial_can_receive1, ++ .fd_read = serial_receive1, ++ .fd_event = serial_event, ++}; ++ + void serial_init_core(SerialState *s) + { + if (!s->chr) { +@@ -690,13 +696,12 @@ void serial_init_core(SerialState *s) + + qemu_register_reset(serial_reset, s); + +- qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1, +- serial_event, s); ++ qemu_chr_add_handlers(s->chr, &serial_handlers, s); + } + + void serial_exit_core(SerialState *s) + { +- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL); ++ qemu_chr_add_handlers(s->chr, NULL, NULL); + qemu_unregister_reset(serial_reset, s); + } + +diff --git a/hw/sh_serial.c b/hw/sh_serial.c +index 9da5d08..260185d 100644 +--- a/hw/sh_serial.c ++++ b/hw/sh_serial.c +@@ -352,6 +352,12 @@ static const MemoryRegionOps sh_serial_ops = { + .endianness = DEVICE_NATIVE_ENDIAN, + }; + ++static const QemuChrHandlers sh_serial_handlers = { ++ .fd_can_read = sh_serial_can_receive1, ++ .fd_read = sh_serial_receive1, ++ .fd_event = sh_serial_event, ++}; ++ + void sh_serial_init(MemoryRegion *sysmem, + hwaddr base, int feat, + uint32_t freq, CharDriverState *chr, +@@ -396,9 +402,9 @@ void sh_serial_init(MemoryRegion *sysmem, + + s->chr = chr; + +- if (chr) +- qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1, +- sh_serial_event, s); ++ if (chr) { ++ qemu_chr_add_handlers(chr, &sh_serial_handlers, s); ++ } + + s->eri = eri_source; + s->rxi = rxi_source; +diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c +index 14f862f..9fbe7dd 100644 +--- a/hw/spapr_vty.c ++++ b/hw/spapr_vty.c +@@ -54,6 +54,11 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len) + qemu_chr_fe_write(dev->chardev, buf, len); + } + ++static const QemuChrHandlers vty_handlers = { ++ .fd_can_read = vty_can_receive, ++ .fd_read = vty_receive, ++}; ++ + static int spapr_vty_init(VIOsPAPRDevice *sdev) + { + VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev; +@@ -63,8 +68,7 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev) + exit(1); + } + +- qemu_chr_add_handlers(dev->chardev, vty_can_receive, +- vty_receive, NULL, dev); ++ qemu_chr_add_handlers(dev->chardev, &vty_handlers, dev); + + return 0; + } +diff --git a/hw/strongarm.c b/hw/strongarm.c +index 4385515..3567218 100644 +--- a/hw/strongarm.c ++++ b/hw/strongarm.c +@@ -1199,6 +1199,12 @@ static const MemoryRegionOps strongarm_uart_ops = { + .endianness = DEVICE_NATIVE_ENDIAN, + }; + ++static const QemuChrHandlers strongarm_uart_handlers = { ++ .fd_can_read = strongarm_uart_can_receive, ++ .fd_read = strongarm_uart_receive, ++ .fd_event = strongarm_uart_event, ++}; ++ + static int strongarm_uart_init(SysBusDevice *dev) + { + StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev); +@@ -1211,11 +1217,7 @@ static int strongarm_uart_init(SysBusDevice *dev) + s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s); + + if (s->chr) { +- qemu_chr_add_handlers(s->chr, +- strongarm_uart_can_receive, +- strongarm_uart_receive, +- strongarm_uart_event, +- s); ++ qemu_chr_add_handlers(s->chr, &strongarm_uart_handlers, s); + } + + return 0; +diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c +index 99b19df..7307ad2 100644 +--- a/hw/usb/dev-serial.c ++++ b/hw/usb/dev-serial.c +@@ -414,7 +414,7 @@ static void usb_serial_handle_destroy(USBDevice *dev) + { + USBSerialState *s = (USBSerialState *)dev; + +- qemu_chr_add_handlers(s->cs, NULL, NULL, NULL, NULL); ++ qemu_chr_add_handlers(s->cs, NULL, NULL); + } + + static int usb_serial_can_read(void *opaque) +@@ -478,6 +478,12 @@ static void usb_serial_event(void *opaque, int event) + } + } + ++static const QemuChrHandlers usb_serial_handlers = { ++ .fd_can_read = usb_serial_can_read, ++ .fd_read = usb_serial_read, ++ .fd_event = usb_serial_event, ++}; ++ + static int usb_serial_initfn(USBDevice *dev) + { + USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev); +@@ -491,8 +497,7 @@ static int usb_serial_initfn(USBDevice *dev) + return -1; + } + +- qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read, +- usb_serial_event, s); ++ qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s); + usb_serial_handle_reset(dev); + + if (s->cs->opened && !dev->attached) { +diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c +index 490c90f..c921d2d 100644 +--- a/hw/usb/redirect.c ++++ b/hw/usb/redirect.c +@@ -1037,6 +1037,12 @@ static void usbredir_chardev_event(void *opaque, int event) + } + } + ++static const QemuChrHandlers usbredir_chr_handlers = { ++ .fd_can_read = usbredir_chardev_can_read, ++ .fd_read = usbredir_chardev_read, ++ .fd_event = usbredir_chardev_event, ++}; ++ + /* + * init + destroy + */ +@@ -1088,8 +1094,7 @@ static int usbredir_initfn(USBDevice *udev) + + /* Let the backend know we are ready */ + qemu_chr_fe_open(dev->cs); +- qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read, +- usbredir_chardev_read, usbredir_chardev_event, dev); ++ qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev); + + qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev); + add_boot_device_path(dev->bootindex, &udev->qdev, NULL); +diff --git a/hw/virtio-console.c b/hw/virtio-console.c +index cffee3d..066590c 100644 +--- a/hw/virtio-console.c ++++ b/hw/virtio-console.c +@@ -106,6 +106,12 @@ static void chr_event(void *opaque, int event) + } + } + ++static const QemuChrHandlers chr_handlers = { ++ .fd_can_read = chr_can_read, ++ .fd_read = chr_read, ++ .fd_event = chr_event, ++}; ++ + static int virtconsole_initfn(VirtIOSerialPort *port) + { + VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); +@@ -117,8 +123,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port) + } + + if (vcon->chr) { +- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event, +- vcon); ++ qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon); + } + + return 0; +diff --git a/hw/xen_console.c b/hw/xen_console.c +index 9426d73..e9fcadc 100644 +--- a/hw/xen_console.c ++++ b/hw/xen_console.c +@@ -211,6 +211,11 @@ out: + return ret; + } + ++static const QemuChrHandlers xencons_handlers = { ++ .fd_can_read = xencons_can_receive, ++ .fd_read = xencons_receive, ++}; ++ + static int con_initialise(struct XenDevice *xendev) + { + struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); +@@ -231,9 +236,9 @@ static int con_initialise(struct XenDevice *xendev) + return -1; + + xen_be_bind_evtchn(&con->xendev); +- if (con->chr) +- qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive, +- NULL, con); ++ if (con->chr) { ++ qemu_chr_add_handlers(con->chr, &xencons_handlers, con); ++ } + + xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n", + con->ring_ref, +@@ -250,8 +255,9 @@ static void con_disconnect(struct XenDevice *xendev) + if (!xendev->dev) { + return; + } +- if (con->chr) +- qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL); ++ if (con->chr) { ++ qemu_chr_add_handlers(con->chr, NULL, NULL); ++ } + xen_be_unbind_evtchn(&con->xendev); + + if (con->sring) { +diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c +index d20fc41..6605fb1 100644 +--- a/hw/xilinx_uartlite.c ++++ b/hw/xilinx_uartlite.c +@@ -195,6 +195,12 @@ static void uart_event(void *opaque, int event) + + } + ++static const QemuChrHandlers uart_handlers = { ++ .fd_can_read = uart_can_rx, ++ .fd_read = uart_rx, ++ .fd_event = uart_event, ++}; ++ + static int xilinx_uartlite_init(SysBusDevice *dev) + { + struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev); +@@ -207,8 +213,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev) + sysbus_init_mmio(dev, &s->mmio); + + s->chr = qemu_char_get_next_serial(); +- if (s->chr) +- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); ++ if (s->chr) { ++ qemu_chr_add_handlers(s->chr, &uart_handlers, s); ++ } + return 0; + } + +diff --git a/monitor.c b/monitor.c +index c0e32d6..ce0c90a 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -4685,6 +4685,18 @@ static void sortcmdlist(void) + * End: + */ + ++static const QemuChrHandlers monitor_handlers = { ++ .fd_can_read = monitor_can_read, ++ .fd_read = monitor_read, ++ .fd_event = monitor_event, ++}; ++ ++static const QemuChrHandlers monitor_control_handlers = { ++ .fd_can_read = monitor_can_read, ++ .fd_read = monitor_control_read, ++ .fd_event = monitor_control_event, ++}; ++ + void monitor_init(CharDriverState *chr, int flags) + { + static int is_first_init = 1; +@@ -4707,14 +4719,12 @@ void monitor_init(CharDriverState *chr, int flags) + if (monitor_ctrl_mode(mon)) { + mon->mc = g_malloc0(sizeof(MonitorControl)); + /* Control mode requires special handlers */ +- qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read, +- monitor_control_event, mon); ++ qemu_chr_add_handlers(chr, &monitor_control_handlers, mon); + qemu_chr_fe_set_echo(chr, true); + + json_message_parser_init(&mon->mc->parser, handle_qmp_command); + } else { +- qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, +- monitor_event, mon); ++ qemu_chr_add_handlers(chr, &monitor_handlers, mon); + } + + QLIST_INSERT_HEAD(&mon_list, mon, entry); +diff --git a/net/slirp.c b/net/slirp.c +index afb52c3..07ae92f 100644 +--- a/net/slirp.c ++++ b/net/slirp.c +@@ -594,6 +594,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size) + slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size); + } + ++static const QemuChrHandlers guestfwd_handlers = { ++ .fd_can_read = guestfwd_can_read, ++ .fd_read = guestfwd_read, ++}; ++ + static int slirp_guestfwd(SlirpState *s, const char *config_str, + int legacy_format) + { +@@ -659,8 +664,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, + fwd->port = port; + fwd->slirp = s->slirp; + +- qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read, +- NULL, fwd); ++ qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd); + } + return 0; + +diff --git a/qemu-char.c b/qemu-char.c +index 77776dc..97247fb 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -193,19 +193,26 @@ void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...) + va_end(ap); + } + ++static const QemuChrHandlers null_handlers = { ++ /* All handlers are initialised to NULL */ ++}; ++ + void qemu_chr_add_handlers(CharDriverState *s, +- IOCanReadHandler *fd_can_read, +- IOReadHandler *fd_read, +- IOEventHandler *fd_event, +- void *opaque) ++ const QemuChrHandlers *handlers, void *opaque) + { +- if (!opaque && !fd_can_read && !fd_read && !fd_event) { ++ if (!s) { ++ return; ++ } ++ if (!opaque && !handlers) { + /* chr driver being released. */ + ++s->avail_connections; + } +- s->chr_can_read = fd_can_read; +- s->chr_read = fd_read; +- s->chr_event = fd_event; ++ if (!handlers) { ++ handlers = &null_handlers; ++ } ++ s->chr_can_read = handlers->fd_can_read; ++ s->chr_read = handlers->fd_read; ++ s->chr_event = handlers->fd_event; + s->handler_opaque = opaque; + if (s->chr_update_read_handler) + s->chr_update_read_handler(s); +@@ -443,6 +450,12 @@ static void mux_chr_event(void *opaque, int event) + mux_chr_send_event(d, i, event); + } + ++static const QemuChrHandlers mux_chr_handlers = { ++ .fd_can_read = mux_chr_can_read, ++ .fd_read = mux_chr_read, ++ .fd_event = mux_chr_event, ++}; ++ + static void mux_chr_update_read_handler(CharDriverState *chr) + { + MuxDriver *d = chr->opaque; +@@ -457,8 +470,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr) + d->chr_event[d->mux_cnt] = chr->chr_event; + /* Fix up the real driver with mux routines */ + if (d->mux_cnt == 0) { +- qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read, +- mux_chr_event, chr); ++ qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr); + } + if (d->focus != -1) { + mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); +diff --git a/qemu-char.h b/qemu-char.h +index a121e04..ff206cb 100644 +--- a/qemu-char.h ++++ b/qemu-char.h +@@ -223,10 +223,15 @@ void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len); + */ + void qemu_chr_be_event(CharDriverState *s, int event); + +-void qemu_chr_add_handlers(CharDriverState *s, +- IOCanReadHandler *fd_can_read, +- IOReadHandler *fd_read, +- IOEventHandler *fd_event, ++ ++typedef struct QemuChrHandlers { ++ IOCanReadHandler *fd_can_read; ++ IOReadHandler *fd_read; ++ IOHandler *fd_write_unblocked; ++ IOEventHandler *fd_event; ++} QemuChrHandlers; ++ ++void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers, + void *opaque); + + void qemu_chr_generic_open(CharDriverState *s); +diff --git a/qtest.c b/qtest.c +index fbfab4e..4ab5b69 100644 +--- a/qtest.c ++++ b/qtest.c +@@ -416,6 +416,13 @@ static void qtest_event(void *opaque, int event) + } + } + ++static const QemuChrHandlers test_handlers = { ++ .fd_can_read = qtest_can_read, ++ .fd_read = qtest_read, ++ .fd_event = qtest_event, ++}; ++ ++ + int qtest_init(void) + { + CharDriverState *chr; +@@ -425,7 +432,7 @@ int qtest_init(void) + configure_icount("0"); + chr = qemu_chr_new("qtest", qtest_chrdev, NULL); + +- qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr); ++ qemu_chr_add_handlers(chr, &test_handlers, chr); + qemu_chr_fe_set_echo(chr, true); + + inbuf = g_string_new(""); +-- +1.8.1 + diff --git a/0102-iohandlers-Add-enable-disable_write_fd_handler-funct.patch b/0102-iohandlers-Add-enable-disable_write_fd_handler-funct.patch deleted file mode 100644 index 95a6996..0000000 --- a/0102-iohandlers-Add-enable-disable_write_fd_handler-funct.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 448ba28f493820e91b65986901165cb28ff5fd78 Mon Sep 17 00:00:00 2001 -Message-Id: <448ba28f493820e91b65986901165cb28ff5fd78.1354903384.git.crobinso@redhat.com> -In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Amit Shah -Date: Mon, 21 Mar 2011 20:32:58 +0100 -Subject: [PATCH] iohandlers: Add enable/disable_write_fd_handler() functions - -These will be used to provide a cleaner API for the nonblocking case. - -Signed-off-by: Amit Shah -Signed-off-by: Cole Robinson ---- - iohandler.c | 35 +++++++++++++++++++++++++++++++++++ - main-loop.h | 3 +++ - 2 files changed, 38 insertions(+) - -diff --git a/iohandler.c b/iohandler.c -index 60460a6..6cf2cdd 100644 ---- a/iohandler.c -+++ b/iohandler.c -@@ -46,6 +46,41 @@ typedef struct IOHandlerRecord { - static QLIST_HEAD(, IOHandlerRecord) io_handlers = - QLIST_HEAD_INITIALIZER(io_handlers); - -+static IOHandlerRecord *find_iohandler(int fd) -+{ -+ IOHandlerRecord *ioh; -+ -+ QLIST_FOREACH(ioh, &io_handlers, next) { -+ if (ioh->fd == fd) { -+ return ioh; -+ } -+ } -+ return NULL; -+} -+ -+void enable_write_fd_handler(int fd, IOHandler *fd_write) -+{ -+ IOHandlerRecord *ioh; -+ -+ ioh = find_iohandler(fd); -+ if (!ioh) { -+ return; -+ } -+ -+ ioh->fd_write = fd_write; -+} -+ -+void disable_write_fd_handler(int fd) -+{ -+ IOHandlerRecord *ioh; -+ -+ ioh = find_iohandler(fd); -+ if (!ioh) { -+ return; -+ } -+ -+ ioh->fd_write = NULL; -+} - - /* XXX: fd_read_poll should be suppressed, but an API change is - necessary in the character devices to suppress fd_can_read(). */ -diff --git a/main-loop.h b/main-loop.h -index 326c742..883ad43 100644 ---- a/main-loop.h -+++ b/main-loop.h -@@ -166,6 +166,9 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque); - typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); - typedef int IOCanReadHandler(void *opaque); - -+void enable_write_fd_handler(int fd, IOHandler *fd_write); -+void disable_write_fd_handler(int fd); -+ - /** - * qemu_set_fd_handler2: Register a file descriptor with the main loop - * --- -1.8.0 - diff --git a/0103-char-Add-framework-for-a-write-unblocked-callback.patch b/0103-char-Add-framework-for-a-write-unblocked-callback.patch deleted file mode 100644 index 9388d16..0000000 --- a/0103-char-Add-framework-for-a-write-unblocked-callback.patch +++ /dev/null @@ -1,65 +0,0 @@ -From ea5fefd1ca7fb951c534333a78618ec6d6d89581 Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Amit Shah -Date: Mon, 21 Mar 2011 21:41:42 +0100 -Subject: [PATCH] char: Add framework for a 'write unblocked' callback - -The char layer can let users know that the driver will block on further -input. For users interested in not blocking, they can assign a function -pointer that will be called back when the driver becomes writable. This -patch just adds the function pointers to the CharDriverState structure, -future patches will enable the nonblocking and callback functionality. - -Signed-off-by: Amit Shah -Signed-off-by: Cole Robinson ---- - qemu-char.c | 3 +++ - qemu-char.h | 4 ++++ - 2 files changed, 7 insertions(+) - -diff --git a/qemu-char.c b/qemu-char.c -index 97247fb..c9e6e36 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -212,11 +212,14 @@ void qemu_chr_add_handlers(CharDriverState *s, - } - s->chr_can_read = handlers->fd_can_read; - s->chr_read = handlers->fd_read; -+ s->chr_write_unblocked = handlers->fd_write_unblocked; - s->chr_event = handlers->fd_event; - s->handler_opaque = opaque; - if (s->chr_update_read_handler) - s->chr_update_read_handler(s); - -+ s->write_blocked = false; -+ - /* We're connecting to an already opened device, so let's make sure we - also get the open event */ - if (s->opened) { -diff --git a/qemu-char.h b/qemu-char.h -index ff206cb..9e1b0f1 100644 ---- a/qemu-char.h -+++ b/qemu-char.h -@@ -63,6 +63,9 @@ struct CharDriverState { - IOEventHandler *chr_event; - IOCanReadHandler *chr_can_read; - IOReadHandler *chr_read; -+ IOHandler *chr_write_unblocked; -+ void (*chr_enable_write_fd_handler)(struct CharDriverState *chr); -+ void (*chr_disable_write_fd_handler)(struct CharDriverState *chr); - void *handler_opaque; - void (*chr_close)(struct CharDriverState *chr); - void (*chr_accept_input)(struct CharDriverState *chr); -@@ -75,6 +78,7 @@ struct CharDriverState { - char *filename; - int opened; - int avail_connections; -+ bool write_blocked; /* Are we in a blocked state? */ - QTAILQ_ENTRY(CharDriverState) next; - }; - --- -1.8.0 - diff --git a/0103-iohandlers-Add-enable-disable_write_fd_handler-funct.patch b/0103-iohandlers-Add-enable-disable_write_fd_handler-funct.patch new file mode 100644 index 0000000..cbbf8f3 --- /dev/null +++ b/0103-iohandlers-Add-enable-disable_write_fd_handler-funct.patch @@ -0,0 +1,77 @@ +From ebe349109322787302da1f65709b77568055ce96 Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Mon, 21 Mar 2011 20:32:58 +0100 +Subject: [PATCH] iohandlers: Add enable/disable_write_fd_handler() functions + +These will be used to provide a cleaner API for the nonblocking case. + +Signed-off-by: Amit Shah +Signed-off-by: Cole Robinson +--- + iohandler.c | 35 +++++++++++++++++++++++++++++++++++ + main-loop.h | 3 +++ + 2 files changed, 38 insertions(+) + +diff --git a/iohandler.c b/iohandler.c +index 60460a6..6cf2cdd 100644 +--- a/iohandler.c ++++ b/iohandler.c +@@ -46,6 +46,41 @@ typedef struct IOHandlerRecord { + static QLIST_HEAD(, IOHandlerRecord) io_handlers = + QLIST_HEAD_INITIALIZER(io_handlers); + ++static IOHandlerRecord *find_iohandler(int fd) ++{ ++ IOHandlerRecord *ioh; ++ ++ QLIST_FOREACH(ioh, &io_handlers, next) { ++ if (ioh->fd == fd) { ++ return ioh; ++ } ++ } ++ return NULL; ++} ++ ++void enable_write_fd_handler(int fd, IOHandler *fd_write) ++{ ++ IOHandlerRecord *ioh; ++ ++ ioh = find_iohandler(fd); ++ if (!ioh) { ++ return; ++ } ++ ++ ioh->fd_write = fd_write; ++} ++ ++void disable_write_fd_handler(int fd) ++{ ++ IOHandlerRecord *ioh; ++ ++ ioh = find_iohandler(fd); ++ if (!ioh) { ++ return; ++ } ++ ++ ioh->fd_write = NULL; ++} + + /* XXX: fd_read_poll should be suppressed, but an API change is + necessary in the character devices to suppress fd_can_read(). */ +diff --git a/main-loop.h b/main-loop.h +index 326c742..883ad43 100644 +--- a/main-loop.h ++++ b/main-loop.h +@@ -166,6 +166,9 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque); + typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); + typedef int IOCanReadHandler(void *opaque); + ++void enable_write_fd_handler(int fd, IOHandler *fd_write); ++void disable_write_fd_handler(int fd); ++ + /** + * qemu_set_fd_handler2: Register a file descriptor with the main loop + * +-- +1.8.1 + diff --git a/0104-char-Add-framework-for-a-write-unblocked-callback.patch b/0104-char-Add-framework-for-a-write-unblocked-callback.patch new file mode 100644 index 0000000..7fc3be9 --- /dev/null +++ b/0104-char-Add-framework-for-a-write-unblocked-callback.patch @@ -0,0 +1,62 @@ +From 646046655c6aed23a9e39064242e0803704d74e8 Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Mon, 21 Mar 2011 21:41:42 +0100 +Subject: [PATCH] char: Add framework for a 'write unblocked' callback + +The char layer can let users know that the driver will block on further +input. For users interested in not blocking, they can assign a function +pointer that will be called back when the driver becomes writable. This +patch just adds the function pointers to the CharDriverState structure, +future patches will enable the nonblocking and callback functionality. + +Signed-off-by: Amit Shah +Signed-off-by: Cole Robinson +--- + qemu-char.c | 3 +++ + qemu-char.h | 4 ++++ + 2 files changed, 7 insertions(+) + +diff --git a/qemu-char.c b/qemu-char.c +index 97247fb..c9e6e36 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -212,11 +212,14 @@ void qemu_chr_add_handlers(CharDriverState *s, + } + s->chr_can_read = handlers->fd_can_read; + s->chr_read = handlers->fd_read; ++ s->chr_write_unblocked = handlers->fd_write_unblocked; + s->chr_event = handlers->fd_event; + s->handler_opaque = opaque; + if (s->chr_update_read_handler) + s->chr_update_read_handler(s); + ++ s->write_blocked = false; ++ + /* We're connecting to an already opened device, so let's make sure we + also get the open event */ + if (s->opened) { +diff --git a/qemu-char.h b/qemu-char.h +index ff206cb..9e1b0f1 100644 +--- a/qemu-char.h ++++ b/qemu-char.h +@@ -63,6 +63,9 @@ struct CharDriverState { + IOEventHandler *chr_event; + IOCanReadHandler *chr_can_read; + IOReadHandler *chr_read; ++ IOHandler *chr_write_unblocked; ++ void (*chr_enable_write_fd_handler)(struct CharDriverState *chr); ++ void (*chr_disable_write_fd_handler)(struct CharDriverState *chr); + void *handler_opaque; + void (*chr_close)(struct CharDriverState *chr); + void (*chr_accept_input)(struct CharDriverState *chr); +@@ -75,6 +78,7 @@ struct CharDriverState { + char *filename; + int opened; + int avail_connections; ++ bool write_blocked; /* Are we in a blocked state? */ + QTAILQ_ENTRY(CharDriverState) next; + }; + +-- +1.8.1 + diff --git a/0104-char-Update-send_all-to-handle-nonblocking-chardev-w.patch b/0104-char-Update-send_all-to-handle-nonblocking-chardev-w.patch deleted file mode 100644 index 49f08ff..0000000 --- a/0104-char-Update-send_all-to-handle-nonblocking-chardev-w.patch +++ /dev/null @@ -1,176 +0,0 @@ -From dfbe8c51243ecd2ad33037cfbbb37440cc3d03ee Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Amit Shah -Date: Mon, 21 Mar 2011 22:00:27 +0100 -Subject: [PATCH] char: Update send_all() to handle nonblocking chardev write - requests - -The send_all function is modified to return to the caller in case the -driver cannot handle any more data. It returns -EAGAIN or -WSAEWOULDBLOCK on non-Windows and Windows platforms respectively. This -is only done when the caller sets a callback function handler indicating -it's not interested in blocking till the driver has written out all the -data. - -Currently there's no driver or caller that supports this. Future -commits will add such capability. - -Signed-off-by: Amit Shah -Signed-off-by: Cole Robinson ---- - qemu-char.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ - qemu_socket.h | 2 +- - 2 files changed, 64 insertions(+), 7 deletions(-) - -diff --git a/qemu-char.c b/qemu-char.c -index c9e6e36..53803a3 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -509,7 +509,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) - - - #ifdef _WIN32 --int send_all(int fd, const void *buf, int len1) -+static int do_send(int fd, const void *buf, int len1, bool nonblock) - { - int ret, len; - -@@ -517,9 +517,14 @@ int send_all(int fd, const void *buf, int len1) - while (len > 0) { - ret = send(fd, buf, len, 0); - if (ret < 0) { -+ if (nonblock && len1 - len) { -+ return len1 - len; -+ } - errno = WSAGetLastError(); - if (errno != WSAEWOULDBLOCK) { - return -1; -+ } else if (errno == WSAEWOULDBLOCK && nonblock) { -+ return WSAEWOULDBLOCK; - } - } else if (ret == 0) { - break; -@@ -533,7 +538,7 @@ int send_all(int fd, const void *buf, int len1) - - #else - --int send_all(int fd, const void *_buf, int len1) -+static int do_send(int fd, const void *_buf, int len1, bool nonblock) - { - int ret, len; - const uint8_t *buf = _buf; -@@ -542,8 +547,15 @@ int send_all(int fd, const void *_buf, int len1) - while (len > 0) { - ret = write(fd, buf, len); - if (ret < 0) { -- if (errno != EINTR && errno != EAGAIN) -+ if (nonblock && len1 - len) { -+ return len1 - len; -+ } -+ if (errno == EAGAIN && nonblock) { -+ return -EAGAIN; -+ } -+ if (errno != EINTR && errno != EAGAIN) { - return -1; -+ } - } else if (ret == 0) { - break; - } else { -@@ -558,6 +570,44 @@ int send_all(int fd, const void *_buf, int len1) - #define STDIO_MAX_CLIENTS 1 - static int stdio_nb_clients; - -+int send_all(CharDriverState *chr, int fd, const void *_buf, int len1) -+{ -+ int ret, eagain_errno; -+ bool nonblock; -+ -+ if (chr && chr->write_blocked) { -+ /* -+ * The caller should not send us data while we're blocked, -+ * but this can happen when multiple writers are woken at once, -+ * so simply return -EAGAIN. -+ */ -+ return -EAGAIN; -+ } -+ -+ nonblock = false; -+ /* -+ * Ensure the char backend is able to receive and handle the -+ * 'write unblocked' event before we turn on nonblock support. -+ */ -+ if (chr && chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) { -+ nonblock = true; -+ } -+ ret = do_send(fd, _buf, len1, nonblock); -+ -+#ifdef _WIN32 -+ eagain_errno = WSAEWOULDBLOCK; -+#else -+ eagain_errno = -EAGAIN; -+#endif -+ -+ if (nonblock && (ret == eagain_errno || (ret >= 0 && ret < len1))) { -+ /* Update fd handler to wake up when chr becomes writable */ -+ chr->chr_enable_write_fd_handler(chr); -+ chr->write_blocked = true; -+ } -+ return ret; -+} -+ - #ifndef _WIN32 - - typedef struct { -@@ -569,7 +619,7 @@ typedef struct { - static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - { - FDCharDriver *s = chr->opaque; -- return send_all(s->fd_out, buf, len); -+ return send_all(chr, s->fd_out, buf, len); - } - - static int fd_chr_read_poll(void *opaque) -@@ -888,7 +938,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - pty_chr_update_read_handler(chr); - return 0; - } -- return send_all(s->fd, buf, len); -+ return send_all(chr, s->fd, buf, len); - } - - static int pty_chr_read_poll(void *opaque) -@@ -2179,8 +2229,15 @@ static void tcp_closed(void *opaque) - static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - { - TCPCharDriver *s = chr->opaque; -+ - if (s->connected) { -- return send_all(s->fd, buf, len); -+ int ret; -+ -+ ret = send_all(chr, s->fd, buf, len); -+ if (ret == -1 && errno == EPIPE) { -+ tcp_closed(chr); -+ } -+ return ret; - } else { - /* XXX: indicate an error ? */ - return len; -diff --git a/qemu_socket.h b/qemu_socket.h -index 02490ad..cceab98 100644 ---- a/qemu_socket.h -+++ b/qemu_socket.h -@@ -36,7 +36,7 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); - int socket_set_cork(int fd, int v); - void socket_set_block(int fd); - void socket_set_nonblock(int fd); --int send_all(int fd, const void *buf, int len1); -+int send_all(CharDriverState *chr, int fd, const void *buf, int len1); - - /* callback function for nonblocking connect - * valid fd on success, negative error code on failure --- -1.8.0 - diff --git a/0105-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch b/0105-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch deleted file mode 100644 index 7ff4ab6..0000000 --- a/0105-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 26139c9fd71229699c6d59c31631a539ac3830fd Mon Sep 17 00:00:00 2001 -Message-Id: <26139c9fd71229699c6d59c31631a539ac3830fd.1354903384.git.crobinso@redhat.com> -In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Amit Shah -Date: Mon, 21 Mar 2011 22:02:47 +0100 -Subject: [PATCH] char: Equip the unix/tcp backend to handle nonblocking - writes# - -Now that the infrastructure is in place to return -EAGAIN to callers, -individual char drivers can set their update_fd_handlers() function to -set or remove an fd's write handler. This handler checks if the driver -became writable. - -A generic callback routine is used for unblocking writes and letting -users of chardevs know that a driver became writable again. - -Signed-off-by: Amit Shah -Signed-off-by: Cole Robinson ---- - qemu-char.c | 34 ++++++++++++++++++++++++++++++++++ - 1 file changed, 34 insertions(+) - -diff --git a/qemu-char.c b/qemu-char.c -index 53803a3..e7cd42a 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -106,6 +106,19 @@ - static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs = - QTAILQ_HEAD_INITIALIZER(chardevs); - -+/* -+ * Generic routine that gets called when chardev becomes writable. -+ * Lets chardev user know it's OK to send more data. -+ */ -+static void char_write_unblocked(void *opaque) -+{ -+ CharDriverState *chr = opaque; -+ -+ chr->write_blocked = false; -+ chr->chr_disable_write_fd_handler(chr); -+ chr->chr_write_unblocked(chr->handler_opaque); -+} -+ - void qemu_chr_be_event(CharDriverState *s, int event) - { - /* Keep track if the char device is open */ -@@ -2508,6 +2521,25 @@ static void tcp_chr_close(CharDriverState *chr) - qemu_chr_be_event(chr, CHR_EVENT_CLOSED); - } - -+static void tcp_enable_write_fd_handler(CharDriverState *chr) -+{ -+ TCPCharDriver *s = chr->opaque; -+ -+ /* -+ * This function is called only after tcp_chr_connect() is called -+ * (either in 'server' mode or client mode. So we're sure of -+ * s->fd being initialised. -+ */ -+ enable_write_fd_handler(s->fd, char_write_unblocked); -+} -+ -+static void tcp_disable_write_fd_handler(CharDriverState *chr) -+{ -+ TCPCharDriver *s = chr->opaque; -+ -+ disable_write_fd_handler(s->fd); -+} -+ - static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) - { - CharDriverState *chr = NULL; -@@ -2563,6 +2595,8 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) - chr->chr_close = tcp_chr_close; - chr->get_msgfd = tcp_get_msgfd; - chr->chr_add_client = tcp_chr_add_client; -+ chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler; -+ chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler; - - if (is_listen) { - s->listen_fd = fd; --- -1.8.0 - diff --git a/0105-char-Update-send_all-to-handle-nonblocking-chardev-w.patch b/0105-char-Update-send_all-to-handle-nonblocking-chardev-w.patch new file mode 100644 index 0000000..af5fba1 --- /dev/null +++ b/0105-char-Update-send_all-to-handle-nonblocking-chardev-w.patch @@ -0,0 +1,173 @@ +From 98984a6b82406c233819a7afa7f35d3df4c386b0 Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Mon, 21 Mar 2011 22:00:27 +0100 +Subject: [PATCH] char: Update send_all() to handle nonblocking chardev write + requests + +The send_all function is modified to return to the caller in case the +driver cannot handle any more data. It returns -EAGAIN or +WSAEWOULDBLOCK on non-Windows and Windows platforms respectively. This +is only done when the caller sets a callback function handler indicating +it's not interested in blocking till the driver has written out all the +data. + +Currently there's no driver or caller that supports this. Future +commits will add such capability. + +Signed-off-by: Amit Shah +Signed-off-by: Cole Robinson +--- + qemu-char.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ + qemu_socket.h | 2 +- + 2 files changed, 64 insertions(+), 7 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index c9e6e36..53803a3 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -509,7 +509,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) + + + #ifdef _WIN32 +-int send_all(int fd, const void *buf, int len1) ++static int do_send(int fd, const void *buf, int len1, bool nonblock) + { + int ret, len; + +@@ -517,9 +517,14 @@ int send_all(int fd, const void *buf, int len1) + while (len > 0) { + ret = send(fd, buf, len, 0); + if (ret < 0) { ++ if (nonblock && len1 - len) { ++ return len1 - len; ++ } + errno = WSAGetLastError(); + if (errno != WSAEWOULDBLOCK) { + return -1; ++ } else if (errno == WSAEWOULDBLOCK && nonblock) { ++ return WSAEWOULDBLOCK; + } + } else if (ret == 0) { + break; +@@ -533,7 +538,7 @@ int send_all(int fd, const void *buf, int len1) + + #else + +-int send_all(int fd, const void *_buf, int len1) ++static int do_send(int fd, const void *_buf, int len1, bool nonblock) + { + int ret, len; + const uint8_t *buf = _buf; +@@ -542,8 +547,15 @@ int send_all(int fd, const void *_buf, int len1) + while (len > 0) { + ret = write(fd, buf, len); + if (ret < 0) { +- if (errno != EINTR && errno != EAGAIN) ++ if (nonblock && len1 - len) { ++ return len1 - len; ++ } ++ if (errno == EAGAIN && nonblock) { ++ return -EAGAIN; ++ } ++ if (errno != EINTR && errno != EAGAIN) { + return -1; ++ } + } else if (ret == 0) { + break; + } else { +@@ -558,6 +570,44 @@ int send_all(int fd, const void *_buf, int len1) + #define STDIO_MAX_CLIENTS 1 + static int stdio_nb_clients; + ++int send_all(CharDriverState *chr, int fd, const void *_buf, int len1) ++{ ++ int ret, eagain_errno; ++ bool nonblock; ++ ++ if (chr && chr->write_blocked) { ++ /* ++ * The caller should not send us data while we're blocked, ++ * but this can happen when multiple writers are woken at once, ++ * so simply return -EAGAIN. ++ */ ++ return -EAGAIN; ++ } ++ ++ nonblock = false; ++ /* ++ * Ensure the char backend is able to receive and handle the ++ * 'write unblocked' event before we turn on nonblock support. ++ */ ++ if (chr && chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) { ++ nonblock = true; ++ } ++ ret = do_send(fd, _buf, len1, nonblock); ++ ++#ifdef _WIN32 ++ eagain_errno = WSAEWOULDBLOCK; ++#else ++ eagain_errno = -EAGAIN; ++#endif ++ ++ if (nonblock && (ret == eagain_errno || (ret >= 0 && ret < len1))) { ++ /* Update fd handler to wake up when chr becomes writable */ ++ chr->chr_enable_write_fd_handler(chr); ++ chr->write_blocked = true; ++ } ++ return ret; ++} ++ + #ifndef _WIN32 + + typedef struct { +@@ -569,7 +619,7 @@ typedef struct { + static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) + { + FDCharDriver *s = chr->opaque; +- return send_all(s->fd_out, buf, len); ++ return send_all(chr, s->fd_out, buf, len); + } + + static int fd_chr_read_poll(void *opaque) +@@ -888,7 +938,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len) + pty_chr_update_read_handler(chr); + return 0; + } +- return send_all(s->fd, buf, len); ++ return send_all(chr, s->fd, buf, len); + } + + static int pty_chr_read_poll(void *opaque) +@@ -2179,8 +2229,15 @@ static void tcp_closed(void *opaque) + static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) + { + TCPCharDriver *s = chr->opaque; ++ + if (s->connected) { +- return send_all(s->fd, buf, len); ++ int ret; ++ ++ ret = send_all(chr, s->fd, buf, len); ++ if (ret == -1 && errno == EPIPE) { ++ tcp_closed(chr); ++ } ++ return ret; + } else { + /* XXX: indicate an error ? */ + return len; +diff --git a/qemu_socket.h b/qemu_socket.h +index 02490ad..cceab98 100644 +--- a/qemu_socket.h ++++ b/qemu_socket.h +@@ -36,7 +36,7 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); + int socket_set_cork(int fd, int v); + void socket_set_block(int fd); + void socket_set_nonblock(int fd); +-int send_all(int fd, const void *buf, int len1); ++int send_all(CharDriverState *chr, int fd, const void *buf, int len1); + + /* callback function for nonblocking connect + * valid fd on success, negative error code on failure +-- +1.8.1 + diff --git a/0106-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch b/0106-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch new file mode 100644 index 0000000..0958e59 --- /dev/null +++ b/0106-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch @@ -0,0 +1,82 @@ +From e8a6c8da28eb73704099b4ae2172bca7fa4d0bd7 Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Mon, 21 Mar 2011 22:02:47 +0100 +Subject: [PATCH] char: Equip the unix/tcp backend to handle nonblocking + writes# + +Now that the infrastructure is in place to return -EAGAIN to callers, +individual char drivers can set their update_fd_handlers() function to +set or remove an fd's write handler. This handler checks if the driver +became writable. + +A generic callback routine is used for unblocking writes and letting +users of chardevs know that a driver became writable again. + +Signed-off-by: Amit Shah +Signed-off-by: Cole Robinson +--- + qemu-char.c | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/qemu-char.c b/qemu-char.c +index 53803a3..e7cd42a 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -106,6 +106,19 @@ + static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs = + QTAILQ_HEAD_INITIALIZER(chardevs); + ++/* ++ * Generic routine that gets called when chardev becomes writable. ++ * Lets chardev user know it's OK to send more data. ++ */ ++static void char_write_unblocked(void *opaque) ++{ ++ CharDriverState *chr = opaque; ++ ++ chr->write_blocked = false; ++ chr->chr_disable_write_fd_handler(chr); ++ chr->chr_write_unblocked(chr->handler_opaque); ++} ++ + void qemu_chr_be_event(CharDriverState *s, int event) + { + /* Keep track if the char device is open */ +@@ -2508,6 +2521,25 @@ static void tcp_chr_close(CharDriverState *chr) + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); + } + ++static void tcp_enable_write_fd_handler(CharDriverState *chr) ++{ ++ TCPCharDriver *s = chr->opaque; ++ ++ /* ++ * This function is called only after tcp_chr_connect() is called ++ * (either in 'server' mode or client mode. So we're sure of ++ * s->fd being initialised. ++ */ ++ enable_write_fd_handler(s->fd, char_write_unblocked); ++} ++ ++static void tcp_disable_write_fd_handler(CharDriverState *chr) ++{ ++ TCPCharDriver *s = chr->opaque; ++ ++ disable_write_fd_handler(s->fd); ++} ++ + static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) + { + CharDriverState *chr = NULL; +@@ -2563,6 +2595,8 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) + chr->chr_close = tcp_chr_close; + chr->get_msgfd = tcp_get_msgfd; + chr->chr_add_client = tcp_chr_add_client; ++ chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler; ++ chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler; + + if (is_listen) { + s->listen_fd = fd; +-- +1.8.1 + diff --git a/0106-char-Throttle-when-host-connection-is-down.patch b/0106-char-Throttle-when-host-connection-is-down.patch deleted file mode 100644 index d373330..0000000 --- a/0106-char-Throttle-when-host-connection-is-down.patch +++ /dev/null @@ -1,60 +0,0 @@ -From c2ddb156db52808a89d91edf5bb1449f226d3ecd Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Amit Shah -Date: Mon, 21 Mar 2011 22:05:10 +0100 -Subject: [PATCH] char: Throttle when host connection is down# - -When the host-side connection goes down, throttle the virtio-serial bus -and later unthrottle when a connection gets established. This helps -prevent any lost IO (guest->host) while the host connection was down. - -Bugzilla: 621484 - -This commit actually helps the bug mentioned above as no writes will now -get lost because of the throttling done here. With just the patches -sent earlier for that bug, one write will end up getting lost in the -worst case (host d/c, guest write, host connect). - -Signed-off-by: Amit Shah -Signed-off-by: Cole Robinson ---- - qemu-char.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/qemu-char.c b/qemu-char.c -index e7cd42a..5c71f0c 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -140,6 +140,9 @@ static void qemu_chr_fire_open_event(void *opaque) - { - CharDriverState *s = opaque; - qemu_chr_be_event(s, CHR_EVENT_OPENED); -+ if (s->write_blocked) { -+ char_write_unblocked(s); -+ } - qemu_free_timer(s->open_timer); - s->open_timer = NULL; - } -@@ -2249,6 +2252,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - ret = send_all(chr, s->fd, buf, len); - if (ret == -1 && errno == EPIPE) { - tcp_closed(chr); -+ -+ if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) { -+ /* -+ * Since we haven't written out anything, let's say -+ * we're throttled. This will prevent any output from -+ * the guest getting lost if host-side chardev goes -+ * down. Unthrottle when we re-connect. -+ */ -+ chr->write_blocked = true; -+ return 0; -+ } - } - return ret; - } else { --- -1.8.0 - diff --git a/0107-char-Throttle-when-host-connection-is-down.patch b/0107-char-Throttle-when-host-connection-is-down.patch new file mode 100644 index 0000000..a62a123 --- /dev/null +++ b/0107-char-Throttle-when-host-connection-is-down.patch @@ -0,0 +1,57 @@ +From 7ce910503a5db38f23a13ae5f56e256d80caf1e4 Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Mon, 21 Mar 2011 22:05:10 +0100 +Subject: [PATCH] char: Throttle when host connection is down# + +When the host-side connection goes down, throttle the virtio-serial bus +and later unthrottle when a connection gets established. This helps +prevent any lost IO (guest->host) while the host connection was down. + +Bugzilla: 621484 + +This commit actually helps the bug mentioned above as no writes will now +get lost because of the throttling done here. With just the patches +sent earlier for that bug, one write will end up getting lost in the +worst case (host d/c, guest write, host connect). + +Signed-off-by: Amit Shah +Signed-off-by: Cole Robinson +--- + qemu-char.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/qemu-char.c b/qemu-char.c +index e7cd42a..5c71f0c 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -140,6 +140,9 @@ static void qemu_chr_fire_open_event(void *opaque) + { + CharDriverState *s = opaque; + qemu_chr_be_event(s, CHR_EVENT_OPENED); ++ if (s->write_blocked) { ++ char_write_unblocked(s); ++ } + qemu_free_timer(s->open_timer); + s->open_timer = NULL; + } +@@ -2249,6 +2252,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) + ret = send_all(chr, s->fd, buf, len); + if (ret == -1 && errno == EPIPE) { + tcp_closed(chr); ++ ++ if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) { ++ /* ++ * Since we haven't written out anything, let's say ++ * we're throttled. This will prevent any output from ++ * the guest getting lost if host-side chardev goes ++ * down. Unthrottle when we re-connect. ++ */ ++ chr->write_blocked = true; ++ return 0; ++ } + } + return ret; + } else { +-- +1.8.1 + diff --git a/0107-virtio-console-Enable-port-throttling-when-chardev-i.patch b/0107-virtio-console-Enable-port-throttling-when-chardev-i.patch deleted file mode 100644 index 7435322..0000000 --- a/0107-virtio-console-Enable-port-throttling-when-chardev-i.patch +++ /dev/null @@ -1,53 +0,0 @@ -From afae0976cf4e3ba7f2810c1afaecac96646a2a2b Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Amit Shah -Date: Mon, 21 Mar 2011 22:06:41 +0100 -Subject: [PATCH] virtio-console: Enable port throttling when chardev is slow - to consume data - -When a chardev indicates it can't accept more data, we tell the -virtio-serial code to stop sending us any more data till we tell -otherwise. This helps in guests continuing to run normally while the vq -keeps getting full and eventually the guest stops queueing more data. -As soon as the chardev indicates it can accept more data, start pushing! - -Signed-off-by: Amit Shah -Signed-off-by: Cole Robinson ---- - hw/virtio-console.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/hw/virtio-console.c b/hw/virtio-console.c -index 066590c..2b5e515 100644 ---- a/hw/virtio-console.c -+++ b/hw/virtio-console.c -@@ -20,6 +20,16 @@ typedef struct VirtConsole { - CharDriverState *chr; - } VirtConsole; - -+/* -+ * Callback function that's called from chardevs when backend becomes -+ * writable. -+ */ -+static void chr_write_unblocked(void *opaque) -+{ -+ VirtConsole *vcon = opaque; -+ -+ virtio_serial_throttle_port(&vcon->port, false); -+} - - /* Callback function that's called when the guest sends us data */ - static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len) -@@ -110,6 +120,7 @@ static const QemuChrHandlers chr_handlers = { - .fd_can_read = chr_can_read, - .fd_read = chr_read, - .fd_event = chr_event, -+ .fd_write_unblocked = chr_write_unblocked, - }; - - static int virtconsole_initfn(VirtIOSerialPort *port) --- -1.8.0 - diff --git a/0108-spice-qemu-char.c-add-throttling.patch b/0108-spice-qemu-char.c-add-throttling.patch deleted file mode 100644 index 0e7b992..0000000 --- a/0108-spice-qemu-char.c-add-throttling.patch +++ /dev/null @@ -1,138 +0,0 @@ -From bffc95c205b473df9bba81dbf676504d0981d392 Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Alon Levy -Date: Tue, 22 Mar 2011 12:27:59 +0200 -Subject: [PATCH] spice-qemu-char.c: add throttling - -BZ: 672191 - -upstream: not submitted (explained below) - -Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing: -1. spice-server: reds.c: read_from_vdi_port -2. qemu: spice-qemu-char.c: vmc_read -3. chr_write_unblocked - (calls virtio_serial_throttle_port(port, false)) -4. qemu: virtio ... -5. qemu: spice-qemu-char.c: spice_chr_write -6. qemu: spice-qemu-char.c: wakeup (calls into spice-server) -7. spice-server: ... -8. qemu: spice-qemu-char.c: vmc_read - -Instead, in vmc_read if we were throttled and we are just about to return -all the bytes we will set a timer to be triggered immediately to call -chr_write_unblocked. Then we return after 2 above, and 3 is called from the -timer callback. This also means we can later remove some ugly recursion protection -from spice-server. - -The other tricky point in this patch is not returning the leftover chunk twice. -When we throttle, by definition we have data that spice server didn't consume. -It is being kept by virtio-serial, and by us. The next vmc_read callback needs -to not return it, but just do unthrottling. Then virtio will give us the remaining -chunk as usual in spice_chr_write, and we will pass it to spice server in the -next vmc_read. - -This patch relies on Amit's series to expose throttling to chardev's, which -was not accepted upstream, and will not be accepted upstream until the mainloop -is reworked to use glib. - -Signed-off-by: Cole Robinson ---- - spice-qemu-char.c | 39 +++++++++++++++++++++++++++++++++++---- - 1 file changed, 35 insertions(+), 4 deletions(-) - -diff --git a/spice-qemu-char.c b/spice-qemu-char.c -index 09aa22d..fba2bfb 100644 ---- a/spice-qemu-char.c -+++ b/spice-qemu-char.c -@@ -1,4 +1,6 @@ - #include "config-host.h" -+#include "qemu-common.h" -+#include "qemu-timer.h" - #include "trace.h" - #include "ui/qemu-spice.h" - #include -@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver { - uint8_t *datapos; - ssize_t bufsize, datalen; - uint32_t debug; -+ QEMUTimer *unblock_timer; - } SpiceCharDriver; - - static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) -@@ -50,6 +53,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) - return out; - } - -+static void spice_chr_unblock(void *opaque) -+{ -+ SpiceCharDriver *scd = opaque; -+ -+ if (scd->chr->chr_write_unblocked == NULL) { -+ dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__); -+ return; -+ } -+ scd->chr->chr_write_unblocked(scd->chr->handler_opaque); -+} -+ - static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) - { - SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); -@@ -61,9 +75,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) - scd->datapos += bytes; - scd->datalen -= bytes; - assert(scd->datalen >= 0); -- if (scd->datalen == 0) { -- scd->datapos = 0; -- } -+ } -+ if (scd->datalen == 0 && scd->chr->write_blocked) { -+ dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes); -+ scd->chr->write_blocked = false; -+ /* -+ * set a timer instead of calling scd->chr->chr_write_unblocked directly, -+ * because that will call back into spice_chr_write (see -+ * virtio-console.c:chr_write_unblocked), which is unwanted. -+ */ -+ qemu_mod_timer(scd->unblock_timer, 0); - } - trace_spice_vmc_read(bytes, len); - return bytes; -@@ -135,6 +156,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd) - static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - { - SpiceCharDriver *s = chr->opaque; -+ int read_bytes; - - dprintf(s, 2, "%s: %d\n", __func__, len); - vmc_register_interface(s); -@@ -147,7 +169,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - s->datapos = s->buffer; - s->datalen = len; - spice_server_char_device_wakeup(&s->sin); -- return len; -+ read_bytes = len - s->datalen; -+ if (read_bytes != len) { -+ dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__, -+ read_bytes, len, s->bufsize); -+ s->chr->write_blocked = true; -+ /* We'll get passed in the unconsumed data with the next call */ -+ s->datalen = 0; -+ } -+ return read_bytes; - } - - static void spice_chr_close(struct CharDriverState *chr) -@@ -225,6 +255,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts) - chr->chr_close = spice_chr_close; - chr->chr_guest_open = spice_chr_guest_open; - chr->chr_guest_close = spice_chr_guest_close; -+ s->unblock_timer = qemu_new_timer_ms(vm_clock, spice_chr_unblock, s); - - #if SPICE_SERVER_VERSION < 0x000901 - /* See comment in vmc_state() */ --- -1.8.0 - diff --git a/0108-virtio-console-Enable-port-throttling-when-chardev-i.patch b/0108-virtio-console-Enable-port-throttling-when-chardev-i.patch new file mode 100644 index 0000000..5662289 --- /dev/null +++ b/0108-virtio-console-Enable-port-throttling-when-chardev-i.patch @@ -0,0 +1,50 @@ +From 8fd5d7cbbb8245185c800062fc6bc0ac9e749375 Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Mon, 21 Mar 2011 22:06:41 +0100 +Subject: [PATCH] virtio-console: Enable port throttling when chardev is slow + to consume data + +When a chardev indicates it can't accept more data, we tell the +virtio-serial code to stop sending us any more data till we tell +otherwise. This helps in guests continuing to run normally while the vq +keeps getting full and eventually the guest stops queueing more data. +As soon as the chardev indicates it can accept more data, start pushing! + +Signed-off-by: Amit Shah +Signed-off-by: Cole Robinson +--- + hw/virtio-console.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/hw/virtio-console.c b/hw/virtio-console.c +index 066590c..2b5e515 100644 +--- a/hw/virtio-console.c ++++ b/hw/virtio-console.c +@@ -20,6 +20,16 @@ typedef struct VirtConsole { + CharDriverState *chr; + } VirtConsole; + ++/* ++ * Callback function that's called from chardevs when backend becomes ++ * writable. ++ */ ++static void chr_write_unblocked(void *opaque) ++{ ++ VirtConsole *vcon = opaque; ++ ++ virtio_serial_throttle_port(&vcon->port, false); ++} + + /* Callback function that's called when the guest sends us data */ + static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len) +@@ -110,6 +120,7 @@ static const QemuChrHandlers chr_handlers = { + .fd_can_read = chr_can_read, + .fd_read = chr_read, + .fd_event = chr_event, ++ .fd_write_unblocked = chr_write_unblocked, + }; + + static int virtconsole_initfn(VirtIOSerialPort *port) +-- +1.8.1 + diff --git a/0109-spice-qemu-char.c-add-throttling.patch b/0109-spice-qemu-char.c-add-throttling.patch new file mode 100644 index 0000000..0b9ffb1 --- /dev/null +++ b/0109-spice-qemu-char.c-add-throttling.patch @@ -0,0 +1,135 @@ +From 283c20975f9fb16afbd1e8ce733f474f5a978939 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Tue, 22 Mar 2011 12:27:59 +0200 +Subject: [PATCH] spice-qemu-char.c: add throttling + +BZ: 672191 + +upstream: not submitted (explained below) + +Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing: +1. spice-server: reds.c: read_from_vdi_port +2. qemu: spice-qemu-char.c: vmc_read +3. chr_write_unblocked + (calls virtio_serial_throttle_port(port, false)) +4. qemu: virtio ... +5. qemu: spice-qemu-char.c: spice_chr_write +6. qemu: spice-qemu-char.c: wakeup (calls into spice-server) +7. spice-server: ... +8. qemu: spice-qemu-char.c: vmc_read + +Instead, in vmc_read if we were throttled and we are just about to return +all the bytes we will set a timer to be triggered immediately to call +chr_write_unblocked. Then we return after 2 above, and 3 is called from the +timer callback. This also means we can later remove some ugly recursion protection +from spice-server. + +The other tricky point in this patch is not returning the leftover chunk twice. +When we throttle, by definition we have data that spice server didn't consume. +It is being kept by virtio-serial, and by us. The next vmc_read callback needs +to not return it, but just do unthrottling. Then virtio will give us the remaining +chunk as usual in spice_chr_write, and we will pass it to spice server in the +next vmc_read. + +This patch relies on Amit's series to expose throttling to chardev's, which +was not accepted upstream, and will not be accepted upstream until the mainloop +is reworked to use glib. + +Signed-off-by: Cole Robinson +--- + spice-qemu-char.c | 39 +++++++++++++++++++++++++++++++++++---- + 1 file changed, 35 insertions(+), 4 deletions(-) + +diff --git a/spice-qemu-char.c b/spice-qemu-char.c +index 09aa22d..fba2bfb 100644 +--- a/spice-qemu-char.c ++++ b/spice-qemu-char.c +@@ -1,4 +1,6 @@ + #include "config-host.h" ++#include "qemu-common.h" ++#include "qemu-timer.h" + #include "trace.h" + #include "ui/qemu-spice.h" + #include +@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver { + uint8_t *datapos; + ssize_t bufsize, datalen; + uint32_t debug; ++ QEMUTimer *unblock_timer; + } SpiceCharDriver; + + static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) +@@ -50,6 +53,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) + return out; + } + ++static void spice_chr_unblock(void *opaque) ++{ ++ SpiceCharDriver *scd = opaque; ++ ++ if (scd->chr->chr_write_unblocked == NULL) { ++ dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__); ++ return; ++ } ++ scd->chr->chr_write_unblocked(scd->chr->handler_opaque); ++} ++ + static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) + { + SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); +@@ -61,9 +75,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) + scd->datapos += bytes; + scd->datalen -= bytes; + assert(scd->datalen >= 0); +- if (scd->datalen == 0) { +- scd->datapos = 0; +- } ++ } ++ if (scd->datalen == 0 && scd->chr->write_blocked) { ++ dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes); ++ scd->chr->write_blocked = false; ++ /* ++ * set a timer instead of calling scd->chr->chr_write_unblocked directly, ++ * because that will call back into spice_chr_write (see ++ * virtio-console.c:chr_write_unblocked), which is unwanted. ++ */ ++ qemu_mod_timer(scd->unblock_timer, 0); + } + trace_spice_vmc_read(bytes, len); + return bytes; +@@ -135,6 +156,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd) + static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) + { + SpiceCharDriver *s = chr->opaque; ++ int read_bytes; + + dprintf(s, 2, "%s: %d\n", __func__, len); + vmc_register_interface(s); +@@ -147,7 +169,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) + s->datapos = s->buffer; + s->datalen = len; + spice_server_char_device_wakeup(&s->sin); +- return len; ++ read_bytes = len - s->datalen; ++ if (read_bytes != len) { ++ dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__, ++ read_bytes, len, s->bufsize); ++ s->chr->write_blocked = true; ++ /* We'll get passed in the unconsumed data with the next call */ ++ s->datalen = 0; ++ } ++ return read_bytes; + } + + static void spice_chr_close(struct CharDriverState *chr) +@@ -225,6 +255,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts) + chr->chr_close = spice_chr_close; + chr->chr_guest_open = spice_chr_guest_open; + chr->chr_guest_close = spice_chr_guest_close; ++ s->unblock_timer = qemu_new_timer_ms(vm_clock, spice_chr_unblock, s); + + #if SPICE_SERVER_VERSION < 0x000901 + /* See comment in vmc_state() */ +-- +1.8.1 + diff --git a/0109-spice-qemu-char.c-remove-intermediate-buffer.patch b/0109-spice-qemu-char.c-remove-intermediate-buffer.patch deleted file mode 100644 index cde302e..0000000 --- a/0109-spice-qemu-char.c-remove-intermediate-buffer.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 52b76076caf6f3f92b83a6f34b70417ddcd3d9d7 Mon Sep 17 00:00:00 2001 -Message-Id: <52b76076caf6f3f92b83a6f34b70417ddcd3d9d7.1354903384.git.crobinso@redhat.com> -In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Alon Levy -Date: Tue, 22 Mar 2011 12:28:00 +0200 -Subject: [PATCH] spice-qemu-char.c: remove intermediate buffer - -BZ: 672191 -upstream: not submitted (explained below) - -virtio-serial's buffer is valid when it calls us, and we don't -access it otherwise: vmc_read is only called in response to wakeup, -or else we set datalen=0 and throttle. Then vmc_read is called back, -we return 0 (not accessing the buffer) and set the timer to unthrottle. - -Also make datalen int and not ssize_t (to fit spice_chr_write signature). - -This relied on the previous patch that introduces throttling, which -can't go upstream right now as explained in that patch. - -Signed-off-by: Cole Robinson ---- - spice-qemu-char.c | 18 ++++++------------ - 1 file changed, 6 insertions(+), 12 deletions(-) - -diff --git a/spice-qemu-char.c b/spice-qemu-char.c -index fba2bfb..ef44bc0 100644 ---- a/spice-qemu-char.c -+++ b/spice-qemu-char.c -@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver { - SpiceCharDeviceInstance sin; - char *subtype; - bool active; -- uint8_t *buffer; -- uint8_t *datapos; -- ssize_t bufsize, datalen; -+ const uint8_t *datapos; -+ int datalen; - uint32_t debug; - QEMUTimer *unblock_timer; - } SpiceCharDriver; -@@ -69,7 +68,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) - SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); - int bytes = MIN(len, scd->datalen); - -- dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen); -+ dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen); - if (bytes > 0) { - memcpy(buf, scd->datapos, bytes); - scd->datapos += bytes; -@@ -161,18 +160,13 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - dprintf(s, 2, "%s: %d\n", __func__, len); - vmc_register_interface(s); - assert(s->datalen == 0); -- if (s->bufsize < len) { -- s->bufsize = len; -- s->buffer = g_realloc(s->buffer, s->bufsize); -- } -- memcpy(s->buffer, buf, len); -- s->datapos = s->buffer; -+ s->datapos = buf; - s->datalen = len; - spice_server_char_device_wakeup(&s->sin); - read_bytes = len - s->datalen; - if (read_bytes != len) { -- dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__, -- read_bytes, len, s->bufsize); -+ dprintf(s, 1, "%s: throttling: %d < %d\n", __func__, -+ read_bytes, len); - s->chr->write_blocked = true; - /* We'll get passed in the unconsumed data with the next call */ - s->datalen = 0; --- -1.8.0 - diff --git a/0110-spice-qemu-char.c-remove-intermediate-buffer.patch b/0110-spice-qemu-char.c-remove-intermediate-buffer.patch new file mode 100644 index 0000000..87a38f7 --- /dev/null +++ b/0110-spice-qemu-char.c-remove-intermediate-buffer.patch @@ -0,0 +1,73 @@ +From 445c0874a4fdc2195f2a2f8a4843377c88323153 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Tue, 22 Mar 2011 12:28:00 +0200 +Subject: [PATCH] spice-qemu-char.c: remove intermediate buffer + +BZ: 672191 +upstream: not submitted (explained below) + +virtio-serial's buffer is valid when it calls us, and we don't +access it otherwise: vmc_read is only called in response to wakeup, +or else we set datalen=0 and throttle. Then vmc_read is called back, +we return 0 (not accessing the buffer) and set the timer to unthrottle. + +Also make datalen int and not ssize_t (to fit spice_chr_write signature). + +This relied on the previous patch that introduces throttling, which +can't go upstream right now as explained in that patch. + +Signed-off-by: Cole Robinson +--- + spice-qemu-char.c | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +diff --git a/spice-qemu-char.c b/spice-qemu-char.c +index fba2bfb..ef44bc0 100644 +--- a/spice-qemu-char.c ++++ b/spice-qemu-char.c +@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver { + SpiceCharDeviceInstance sin; + char *subtype; + bool active; +- uint8_t *buffer; +- uint8_t *datapos; +- ssize_t bufsize, datalen; ++ const uint8_t *datapos; ++ int datalen; + uint32_t debug; + QEMUTimer *unblock_timer; + } SpiceCharDriver; +@@ -69,7 +68,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) + SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); + int bytes = MIN(len, scd->datalen); + +- dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen); ++ dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen); + if (bytes > 0) { + memcpy(buf, scd->datapos, bytes); + scd->datapos += bytes; +@@ -161,18 +160,13 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) + dprintf(s, 2, "%s: %d\n", __func__, len); + vmc_register_interface(s); + assert(s->datalen == 0); +- if (s->bufsize < len) { +- s->bufsize = len; +- s->buffer = g_realloc(s->buffer, s->bufsize); +- } +- memcpy(s->buffer, buf, len); +- s->datapos = s->buffer; ++ s->datapos = buf; + s->datalen = len; + spice_server_char_device_wakeup(&s->sin); + read_bytes = len - s->datalen; + if (read_bytes != len) { +- dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__, +- read_bytes, len, s->bufsize); ++ dprintf(s, 1, "%s: throttling: %d < %d\n", __func__, ++ read_bytes, len); + s->chr->write_blocked = true; + /* We'll get passed in the unconsumed data with the next call */ + s->datalen = 0; +-- +1.8.1 + diff --git a/0110-usb-redir-Add-flow-control-support.patch b/0110-usb-redir-Add-flow-control-support.patch deleted file mode 100644 index 90a6522..0000000 --- a/0110-usb-redir-Add-flow-control-support.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 4e6a76dd0e35b00e9592a53afc8cffac4cc35951 Mon Sep 17 00:00:00 2001 -Message-Id: <4e6a76dd0e35b00e9592a53afc8cffac4cc35951.1354903384.git.crobinso@redhat.com> -In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Hans de Goede -Date: Tue, 19 Jul 2011 10:56:19 +0200 -Subject: [PATCH] usb-redir: Add flow control support - -Signed-off-by: Hans de Goede -Signed-off-by: Cole Robinson ---- - hw/usb/redirect.c | 22 ++++++++++++++++++++-- - 1 file changed, 20 insertions(+), 2 deletions(-) - -diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c -index c921d2d..dfb1773 100644 ---- a/hw/usb/redirect.c -+++ b/hw/usb/redirect.c -@@ -239,8 +239,9 @@ static int usbredir_read(void *priv, uint8_t *data, int count) - static int usbredir_write(void *priv, uint8_t *data, int count) - { - USBRedirDevice *dev = priv; -+ int r; - -- if (!dev->cs->opened) { -+ if (!dev->cs->opened || dev->cs->write_blocked) { - return 0; - } - -@@ -249,7 +250,16 @@ static int usbredir_write(void *priv, uint8_t *data, int count) - return 0; - } - -- return qemu_chr_fe_write(dev->cs, data, count); -+ r = qemu_chr_fe_write(dev->cs, data, count); -+ -+ if (r < 0) { -+ if (dev->cs->write_blocked) { -+ return 0; -+ } -+ return -1; -+ } -+ -+ return r; - } - - /* -@@ -1037,10 +1047,18 @@ static void usbredir_chardev_event(void *opaque, int event) - } - } - -+static void usbredir_chardev_write_unblocked(void *opaque) -+{ -+ USBRedirDevice *dev = opaque; -+ -+ usbredirparser_do_write(dev->parser); -+} -+ - static const QemuChrHandlers usbredir_chr_handlers = { - .fd_can_read = usbredir_chardev_can_read, - .fd_read = usbredir_chardev_read, - .fd_event = usbredir_chardev_event, -+ .fd_write_unblocked = usbredir_chardev_write_unblocked, - }; - - /* --- -1.8.0 - diff --git a/0111-char-Disable-write-callback-if-throttled-chardev-is-.patch b/0111-char-Disable-write-callback-if-throttled-chardev-is-.patch deleted file mode 100644 index cfa9567..0000000 --- a/0111-char-Disable-write-callback-if-throttled-chardev-is-.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 736b3ad749e5c60de44d4c5836b59d2287b6b918 Mon Sep 17 00:00:00 2001 -Message-Id: <736b3ad749e5c60de44d4c5836b59d2287b6b918.1354903384.git.crobinso@redhat.com> -In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Amit Shah -Date: Fri, 2 Dec 2011 15:42:55 +0530 -Subject: [PATCH] char: Disable write callback if throttled chardev is - detached - -If a throttled chardev is detached from the frontend device, all future -callbacks should be suppressed. Not doing this results in a segfault. - -Bugzilla: 745758 -Upstream: Not applicable, since throttling is a RHEL6-only feature. - -Signed-off-by: Amit Shah -Signed-off-by: Cole Robinson ---- - qemu-char.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/qemu-char.c b/qemu-char.c -index 5c71f0c..16ad6b6 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -224,6 +224,11 @@ void qemu_chr_add_handlers(CharDriverState *s, - ++s->avail_connections; - } - if (!handlers) { -+ if (s->write_blocked) { -+ /* Ensure we disable the callback if we were throttled */ -+ s->chr_disable_write_fd_handler(s); -+ /* s->write_blocked is cleared below */ -+ } - handlers = &null_handlers; - } - s->chr_can_read = handlers->fd_can_read; --- -1.8.0 - diff --git a/0111-usb-redir-Add-flow-control-support.patch b/0111-usb-redir-Add-flow-control-support.patch new file mode 100644 index 0000000..bbbdaec --- /dev/null +++ b/0111-usb-redir-Add-flow-control-support.patch @@ -0,0 +1,65 @@ +From 8f9c374199cd82c5364d8f759cd23f2f17f2911f Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 19 Jul 2011 10:56:19 +0200 +Subject: [PATCH] usb-redir: Add flow control support + +Signed-off-by: Hans de Goede +--- + hw/usb/redirect.c | 22 ++++++++++++++++++++-- + 1 file changed, 20 insertions(+), 2 deletions(-) + +diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c +index c921d2d..56c3c24 100644 +--- a/hw/usb/redirect.c ++++ b/hw/usb/redirect.c +@@ -239,8 +239,9 @@ static int usbredir_read(void *priv, uint8_t *data, int count) + static int usbredir_write(void *priv, uint8_t *data, int count) + { + USBRedirDevice *dev = priv; ++ int r; + +- if (!dev->cs->opened) { ++ if (!dev->cs->opened || dev->cs->write_blocked) { + return 0; + } + +@@ -249,7 +250,16 @@ static int usbredir_write(void *priv, uint8_t *data, int count) + return 0; + } + +- return qemu_chr_fe_write(dev->cs, data, count); ++ r = qemu_chr_fe_write(dev->cs, data, count); ++ ++ if (r < 0) { ++ if (dev->cs->write_blocked) { ++ return 0; ++ } ++ return -1; ++ } ++ ++ return r; + } + + /* +@@ -1037,10 +1047,18 @@ static void usbredir_chardev_event(void *opaque, int event) + } + } + ++static void usbredir_chardev_write_unblocked(void *opaque) ++{ ++ USBRedirDevice *dev = opaque; ++ ++ usbredirparser_do_write(dev->parser); ++} ++ + static const QemuChrHandlers usbredir_chr_handlers = { + .fd_can_read = usbredir_chardev_can_read, + .fd_read = usbredir_chardev_read, + .fd_event = usbredir_chardev_event, ++ .fd_write_unblocked = usbredir_chardev_write_unblocked, + }; + + /* +-- +1.8.1 + diff --git a/0112-char-Disable-write-callback-if-throttled-chardev-is-.patch b/0112-char-Disable-write-callback-if-throttled-chardev-is-.patch new file mode 100644 index 0000000..4722f36 --- /dev/null +++ b/0112-char-Disable-write-callback-if-throttled-chardev-is-.patch @@ -0,0 +1,36 @@ +From 824da34c4d46c0e7707198dc0c4714a5ab775251 Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Fri, 2 Dec 2011 15:42:55 +0530 +Subject: [PATCH] char: Disable write callback if throttled chardev is detached + +If a throttled chardev is detached from the frontend device, all future +callbacks should be suppressed. Not doing this results in a segfault. + +Bugzilla: 745758 +Upstream: Not applicable, since throttling is a RHEL6-only feature. + +Signed-off-by: Amit Shah +Signed-off-by: Cole Robinson +--- + qemu-char.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/qemu-char.c b/qemu-char.c +index 5c71f0c..16ad6b6 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -224,6 +224,11 @@ void qemu_chr_add_handlers(CharDriverState *s, + ++s->avail_connections; + } + if (!handlers) { ++ if (s->write_blocked) { ++ /* Ensure we disable the callback if we were throttled */ ++ s->chr_disable_write_fd_handler(s); ++ /* s->write_blocked is cleared below */ ++ } + handlers = &null_handlers; + } + s->chr_can_read = handlers->fd_can_read; +-- +1.8.1 + diff --git a/0112-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch b/0112-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch deleted file mode 100644 index 0247ec7..0000000 --- a/0112-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 1f54fab0e8f692986254b69c607f4151d9743260 Mon Sep 17 00:00:00 2001 -Message-Id: <1f54fab0e8f692986254b69c607f4151d9743260.1354903384.git.crobinso@redhat.com> -In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com> -From: Alon Levy -Date: Fri, 16 Nov 2012 16:24:47 +0200 -Subject: [PATCH] hw/virtio-serial-bus: replay guest open on destination - -This is rewrite of a patch carried in Fedora previously based -on new code upstream, here is the original message, it still applies: -(the original fedora patch was commit id -a9bc20afc1f0604ee81c23b7c67d627e51d2e8d4, this is useful for grepping in -logs, it isn't in upstream) - -When migrating a host with with a spice agent running the mouse becomes -non operational after the migration. This is rhbz #725965. - -The problem is that after migration spice doesn't know the guest agent -is open. Spice is just a char dev here. And a chardev cannot query it's -device, the device has to let the chardev know when it is open. Right -now after migration the chardev which is recreated is in it's default -state, which assumes the guest is disconnected. - -Char devices carry no information across migration, but the -virtio-serial does already carry the guest_connected state. This patch -passes that bit to the chardev. ---- - hw/virtio-serial-bus.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c -index 155da58..fd19984 100644 ---- a/hw/virtio-serial-bus.c -+++ b/hw/virtio-serial-bus.c -@@ -641,6 +641,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque) - VirtIOSerial *s = opaque; - VirtIOSerialPort *port; - uint8_t host_connected; -+ VirtIOSerialPortClass *vsc; - - for (i = 0 ; i < s->post_load.nr_active_ports; ++i) { - port = s->post_load.connected[i].port; -@@ -653,6 +654,11 @@ static void virtio_serial_post_load_timer_cb(void *opaque) - send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, - port->host_connected); - } -+ vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port); -+ if (port->guest_connected && vsc->guest_open) { -+ /* replay guest open */ -+ vsc->guest_open(port); -+ } - } - g_free(s->post_load.connected); - s->post_load.connected = NULL; --- -1.8.0 - diff --git a/0113-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch b/0113-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch new file mode 100644 index 0000000..42a73fd --- /dev/null +++ b/0113-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch @@ -0,0 +1,54 @@ +From ab88ff277044974715aab3fd88b168c00605d193 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Fri, 16 Nov 2012 16:24:47 +0200 +Subject: [PATCH] hw/virtio-serial-bus: replay guest open on destination + +This is rewrite of a patch carried in Fedora previously based +on new code upstream, here is the original message, it still applies: +(the original fedora patch was commit id +a9bc20afc1f0604ee81c23b7c67d627e51d2e8d4, this is useful for grepping in +logs, it isn't in upstream) + +When migrating a host with with a spice agent running the mouse becomes +non operational after the migration. This is rhbz #725965. + +The problem is that after migration spice doesn't know the guest agent +is open. Spice is just a char dev here. And a chardev cannot query it's +device, the device has to let the chardev know when it is open. Right +now after migration the chardev which is recreated is in it's default +state, which assumes the guest is disconnected. + +Char devices carry no information across migration, but the +virtio-serial does already carry the guest_connected state. This patch +passes that bit to the chardev. +--- + hw/virtio-serial-bus.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c +index 155da58..fd19984 100644 +--- a/hw/virtio-serial-bus.c ++++ b/hw/virtio-serial-bus.c +@@ -641,6 +641,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque) + VirtIOSerial *s = opaque; + VirtIOSerialPort *port; + uint8_t host_connected; ++ VirtIOSerialPortClass *vsc; + + for (i = 0 ; i < s->post_load.nr_active_ports; ++i) { + port = s->post_load.connected[i].port; +@@ -653,6 +654,11 @@ static void virtio_serial_post_load_timer_cb(void *opaque) + send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, + port->host_connected); + } ++ vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port); ++ if (port->guest_connected && vsc->guest_open) { ++ /* replay guest open */ ++ vsc->guest_open(port); ++ } + } + g_free(s->post_load.connected); + s->post_load.connected = NULL; +-- +1.8.1 + diff --git a/qemu.spec b/qemu.spec index 2302acd..4432977 100644 --- a/qemu.spec +++ b/qemu.spec @@ -120,7 +120,7 @@ Summary: QEMU is a FAST! processor emulator Name: qemu Version: 1.3.0 -Release: 2%{?dist} +Release: 3%{?dist} # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped Epoch: 2 License: GPLv2+ and LGPLv2+ and BSD @@ -137,25 +137,31 @@ ExclusiveArch: %{kvm_archs} %endif Source0: http://wiki.qemu-project.org/download/%{name}-%{version}.tar.bz2 -# libcacard build fixes (heading upstream) -Patch1: 0000-libcacard-fix-missing-symbols-in-libcacard.so.patch -Patch2: 0001-configure-move-vscclient-binary-under-libcacard.patch -# Fix migration from qemu-kvm 1.2 to qemu 1.3 -Patch3: 0002-Fix-migration-from-qemu-kvm-1.2.patch +# libcacard build fixes (upstream) +Patch0001: 0001-libcacard-fix-missing-symbols-in-libcacard.so.patch +Patch0002: 0002-configure-move-vscclient-binary-under-libcacard.patch + +# Fix test suite on i686 (patch heading upstream) +Patch0003: 0003-rtc-test-skip-year-2038-overflow-check-in-case-time_.patch + +# Fix migration from qemu-kvm 1.2 to qemu 1.3 (non-upstream) +Patch0004: 0004-Fix-migration-compat-with-qemu-kvm.patch + # Flow control series -Patch4: 0100-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch -Patch5: 0101-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch -Patch6: 0102-iohandlers-Add-enable-disable_write_fd_handler-funct.patch -Patch7: 0103-char-Add-framework-for-a-write-unblocked-callback.patch -Patch8: 0104-char-Update-send_all-to-handle-nonblocking-chardev-w.patch -Patch9: 0105-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch -Patch10: 0106-char-Throttle-when-host-connection-is-down.patch -Patch11: 0107-virtio-console-Enable-port-throttling-when-chardev-i.patch -Patch12: 0108-spice-qemu-char.c-add-throttling.patch -Patch13: 0109-spice-qemu-char.c-remove-intermediate-buffer.patch -Patch14: 0110-usb-redir-Add-flow-control-support.patch -Patch15: 0111-char-Disable-write-callback-if-throttled-chardev-is-.patch -Patch16: 0112-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch +Patch0101: 0101-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch +Patch0102: 0102-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch +Patch0103: 0103-iohandlers-Add-enable-disable_write_fd_handler-funct.patch +Patch0104: 0104-char-Add-framework-for-a-write-unblocked-callback.patch +Patch0105: 0105-char-Update-send_all-to-handle-nonblocking-chardev-w.patch +Patch0106: 0106-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch +Patch0107: 0107-char-Throttle-when-host-connection-is-down.patch +Patch0108: 0108-virtio-console-Enable-port-throttling-when-chardev-i.patch +Patch0109: 0109-spice-qemu-char.c-add-throttling.patch +Patch0110: 0110-spice-qemu-char.c-remove-intermediate-buffer.patch +Patch0111: 0111-usb-redir-Add-flow-control-support.patch +Patch0112: 0112-char-Disable-write-callback-if-throttled-chardev-is-.patch +Patch0113: 0113-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch + Source1: qemu.binfmt @@ -362,24 +368,13 @@ with the host over a virtio-serial channel named "org.qemu.guest_agent.0" This package does not need to be installed on the host OS. %post guest-agent -if [ $1 -eq 1 ] ; then - # Initial installation. - /bin/systemctl daemon-reload >/dev/null 2>&1 || : -fi +%systemd_post qemu-guest-agent.service %preun guest-agent -if [ $1 -eq 0 ] ; then - # Package removal, not upgrade. - /bin/systemctl stop qemu-guest-agent.service > /dev/null 2>&1 || : -fi +%systemd_preun qemu-guest-agent.service %postun guest-agent -/bin/systemctl daemon-reload >/dev/null 2>&1 || : -if [ $1 -ge 1 ] ; then - # Package upgrade, not uninstall. - /bin/systemctl try-restart qemu-guest-agent.service >/dev/null 2>&1 || : -fi - +%systemd_postun_with_restart qemu-guest-agent.service %if 0%{?user:1} @@ -626,22 +621,31 @@ CAC emulation development files. %prep %setup -q -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -%patch13 -p1 -%patch14 -p1 -%patch15 -p1 -%patch16 -p1 +# libcacard build fixes (upstream) +%patch0001 -p1 +%patch0002 -p1 + +# Fix test suite on i686 (patch heading upstream) +%patch0003 -p1 + +# Fix migration from qemu-kvm 1.2 to qemu 1.3 (non-upstream) +%patch0004 -p1 + +# Flow control series +%patch0101 -p1 +%patch0102 -p1 +%patch0103 -p1 +%patch0104 -p1 +%patch0105 -p1 +%patch0106 -p1 +%patch0107 -p1 +%patch0108 -p1 +%patch0109 -p1 +%patch0110 -p1 +%patch0111 -p1 +%patch0112 -p1 +%patch0113 -p1 + %build @@ -681,13 +685,19 @@ dobuild() { --sysconfdir=%{_sysconfdir} \ --interp-prefix=%{_prefix}/qemu-%%M \ --audio-drv-list=pa,sdl,alsa,oss \ + --localstatedir=%{_localstatedir} \ + --libexecdir=%{_libexecdir} \ --disable-strip \ --extra-ldflags="$extraldflags -pie -Wl,-z,relro -Wl,-z,now" \ --extra-cflags="%{optflags} -fPIE -DPIE" \ + --enable-mixemu \ + --enable-trace-backend=dtrace \ + --disable-werror \ + --disable-xen \ + --enable-kvm \ %if 0%{?have_spice:1} --enable-spice \ %endif - --enable-mixemu \ %if 0%{?have_seccomp:1} --enable-seccomp \ %endif @@ -699,10 +709,6 @@ dobuild() { %else --disable-fdt \ %endif - --enable-trace-backend=dtrace \ - --disable-werror \ - --disable-xen \ - --enable-kvm \ "$@" echo "config-host.mak contents:" @@ -903,14 +909,9 @@ make %{?_smp_mflags} $buildldflags DESTDIR=$RPM_BUILD_ROOT install-libcacard find $RPM_BUILD_ROOT -name '*.la' -or -name '*.a' | xargs rm -f find $RPM_BUILD_ROOT -name "libcacard.so*" -exec chmod +x \{\} \; -%check -# qemu 1.3 tests fail on i686: -# GTESTER check-qtest-i386 -# ** -# ERROR:tests/rtc-test.c:209:set_year_20xx: assertion failed (cmos_read(RTC_HOURS) == 0x02): (25 == 2) -# GTester: last random seed: R02S3c33904d728a7716fb49ee76edbb6e40 -#make check +%check +make check %ifarch %{kvm_archs} %post %{kvm_package} @@ -920,13 +921,11 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules || : udevadm trigger --sysname-match=kvm || : %endif + %if %{without separate_kvm} %post common -if [ $1 -eq 1 ] ; then - # Initial installation - /bin/systemctl enable ksm.service >/dev/null 2>&1 || : - /bin/systemctl enable ksmtuned.service >/dev/null 2>&1 || : -fi +%systemd_post ksm.service +%systemd_post ksmtuned.service getent group kvm >/dev/null || groupadd -g 36 -r kvm getent group qemu >/dev/null || groupadd -g 107 -r qemu @@ -934,22 +933,15 @@ getent passwd qemu >/dev/null || \ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ -c "qemu user" qemu + %preun common -if [ $1 -eq 0 ] ; then - # Package removal, not upgrade - /bin/systemctl --no-reload disable ksmtuned.service > /dev/null 2>&1 || : - /bin/systemctl --no-reload disable ksm.service > /dev/null 2>&1 || : - /bin/systemctl stop ksmtuned.service > /dev/null 2>&1 || : - /bin/systemctl stop ksm.service > /dev/null 2>&1 || : -fi +%systemd_preun ksm.service +%systemd_preun ksmtuned.service + %postun common -/bin/systemctl daemon-reload >/dev/null 2>&1 || : -if [ $1 -ge 1 ] ; then - # Package upgrade, not uninstall - /bin/systemctl try-restart ksmtuned.service >/dev/null 2>&1 || : - /bin/systemctl try-restart ksm.service >/dev/null 2>&1 || : -fi +%systemd_postun_with_restart ksm.service +%systemd_postun_with_restart ksmtuned.service %endif @@ -1266,6 +1258,11 @@ fi %{_libdir}/pkgconfig/libcacard.pc %changelog +* Tue Jan 15 2013 Cole Robinson - 2:1.3.0-3 +- Fix migration from qemu-kvm +- Fix the test suite on i686 +- Use systemd macros in specfile (bz #850285) + * Tue Jan 15 2013 Hans de Goede - 2:1.3.0-2 - Fix 0110-usb-redir-Add-flow-control-support.patch being mangled on rebase to 1.3.0, breaking usbredir support