* [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze
@ 2017-07-13 14:23 Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 01/41] build: add -Wexpansion-to-defined Paolo Bonzini
` (41 more replies)
0 siblings, 42 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:23 UTC (permalink / raw)
To: qemu-devel
The following changes since commit f0d2ead97cddf622a0478086886cc70a8ed6aeaf:
Merge remote-tracking branch 'remotes/yongbok/tags/mips-20170711' into staging (2017-07-13 12:48:37 +0100)
are available in the git repository at:
git://github.com/bonzini/qemu.git tags/for-upstream
for you to fetch changes up to a5c8d75361054dbf953b87bc9675ecb11433762a:
translate-all: remove redundant !tcg_enabled check in dump_exec_info (2017-07-13 15:43:45 +0200)
----------------------------------------------------------------
* gdbstub fixes (Alex)
* IOMMU MemoryRegion subclass (Alexey)
* Chardev hotswap (Anton)
* NBD_OPT_GO support (Eric)
* Misc bugfixes
* MAINTAINERS updates (Philippe)
----------------------------------------------------------------
I'm away next week, I'd be able to resubmit if there are issues on July 23.
Alex Bennée (4):
gdbstub: modernise DEBUG_GDB
gdbstub: rename cpu_index -> cpu_gdb_index
qom/cpu: remove host_tid field
gdbstub: don't fail on vCont; C04:0; c packets
Alexey Kardashevskiy (2):
memory/iommu: QOM'fy IOMMU MemoryRegion
memory/iommu: introduce IOMMUMemoryRegionClass
Anton Nefedov (13):
char: move QemuOpts->ChardevBackend translation to a separate func
char: add backend hotswap handler
char: chardevice hotswap
char: forbid direct chardevice access for hotswap devices
char: avoid chardevice direct access
test-char: destroy chardev-udp after test
test-char: split char_udp_test
test-char: split char_file_test
test-char: add hotswap test
hmp: add hmp analogue for qmp-chardev-change
virtio-console: chardev hotswap support
serial: move TIOCM update to a separate function
serial: chardev hotswap support
Emilio G. Cota (2):
vl: fix breakage of -tb-size
translate-all: remove redundant !tcg_enabled check in dump_exec_info
Eric Blake (9):
nbd: Create struct for tracking export info
nbd: Don't bother tracing an NBD_OPT_ABORT response failure
nbd: Expose and debug more NBD constants
nbd: Simplify trace of client flags in negotiation
nbd: Refactor reply to NBD_OPT_EXPORT_NAME
nbd: Implement NBD_OPT_GO on server
nbd: Implement NBD_OPT_GO on client
nbd: Implement NBD_INFO_BLOCK_SIZE on server
nbd: Implement NBD_INFO_BLOCK_SIZE on client
Marc-André Lureau (1):
chardev: block during sync read
Paolo Bonzini (1):
build: add -Wexpansion-to-defined
Peng Hao (1):
chardev: fix parallel device can't be reconnect
Philippe Mathieu-Daudé (5):
MAINTAINERS: update TCG entries
MAINTAINERS: update KVM entries
MAINTAINERS: update Xen entries
MAINTAINERS: update TCI entry
MAINTAINERS: add entry for "Unimplemented" device
Pranith Kumar (2):
Revert "exec.c: Fix breakpoint invalidation race"
mttcg/i386: Patch instruction using async_safe_* framework
Prasad J Pandit (1):
exec: use qemu_ram_ptr_length to access guest ram
MAINTAINERS | 18 +--
accel/tcg/translate-all.c | 5 -
backends/rng-egd.c | 2 +-
block/nbd-client.c | 22 +--
block/nbd-client.h | 3 +-
block/nbd.c | 16 ++-
bsd-user/qemu.h | 2 +
chardev/char-fe.c | 16 ++-
chardev/char-mux.c | 1 +
chardev/char-socket.c | 2 +
chardev/char.c | 164 ++++++++++++++++++-----
configure | 2 +-
exec.c | 43 ++++--
gdbstub.c | 119 ++++++++---------
hmp-commands.hx | 18 ++-
hmp.c | 34 +++++
hmp.h | 1 +
hw/alpha/typhoon.c | 31 +++--
hw/arm/pxa2xx.c | 3 +-
hw/arm/strongarm.c | 4 +-
hw/char/bcm2835_aux.c | 2 +-
hw/char/cadence_uart.c | 4 +-
hw/char/debugcon.c | 4 +-
hw/char/digic-uart.c | 2 +-
hw/char/escc.c | 8 +-
hw/char/etraxfs_ser.c | 2 +-
hw/char/exynos4210_uart.c | 4 +-
hw/char/grlib_apbuart.c | 4 +-
hw/char/imx_serial.c | 2 +-
hw/char/ipoctal232.c | 4 +-
hw/char/lm32_juart.c | 2 +-
hw/char/lm32_uart.c | 2 +-
hw/char/mcf_uart.c | 2 +-
hw/char/milkymist-uart.c | 2 +-
hw/char/parallel.c | 8 +-
hw/char/pl011.c | 2 +-
hw/char/sclpconsole-lm.c | 4 +-
hw/char/sclpconsole.c | 4 +-
hw/char/serial.c | 63 +++++++--
hw/char/sh_serial.c | 4 +-
hw/char/spapr_vty.c | 4 +-
hw/char/stm32f2xx_usart.c | 3 +-
hw/char/terminal3270.c | 4 +-
hw/char/virtio-console.c | 35 ++++-
hw/char/xen_console.c | 4 +-
hw/char/xilinx_uartlite.c | 2 +-
hw/dma/rc4030.c | 34 +++--
hw/i386/amd_iommu.c | 33 +++--
hw/i386/amd_iommu.h | 5 +-
hw/i386/intel_iommu.c | 42 ++++--
hw/i386/kvmvapic.c | 85 ++++++------
hw/ipmi/ipmi_bmc_extern.c | 4 +-
hw/mips/boston.c | 2 +-
hw/mips/mips_jazz.c | 2 +-
hw/mips/mips_malta.c | 2 +-
hw/misc/ivshmem.c | 6 +-
hw/pci-host/apb.c | 29 ++--
hw/ppc/spapr_iommu.c | 42 ++++--
hw/s390x/s390-pci-bus.c | 29 ++--
hw/s390x/s390-pci-bus.h | 3 +-
hw/s390x/s390-pci-inst.c | 11 +-
hw/usb/ccid-card-passthru.c | 6 +-
hw/usb/dev-serial.c | 7 +-
hw/usb/redirect.c | 7 +-
hw/vfio/common.c | 12 +-
hw/vfio/spapr.c | 3 +-
include/block/nbd.h | 58 ++++++--
include/chardev/char-fe.h | 22 +++
include/chardev/char.h | 19 +++
include/exec/gdbstub.h | 9 --
include/exec/memory.h | 94 +++++++++----
include/hw/i386/intel_iommu.h | 5 +-
include/hw/mips/mips.h | 2 +-
include/hw/ppc/spapr.h | 7 +-
include/hw/vfio/vfio-common.h | 2 +-
include/qemu/typedefs.h | 1 +
include/qom/cpu.h | 2 -
linux-user/syscall.c | 1 -
memory.c | 113 +++++++++++-----
monitor.c | 4 +-
nbd/client.c | 283 +++++++++++++++++++++++++++++++++------
nbd/common.c | 92 +++++++++++++
nbd/nbd-internal.h | 13 +-
nbd/server.c | 304 +++++++++++++++++++++++++++++++++++-------
nbd/trace-events | 25 ++--
net/colo-compare.c | 10 +-
net/filter-mirror.c | 8 +-
net/slirp.c | 2 +-
net/vhost-user.c | 7 +-
qapi-schema.json | 40 ++++++
qemu-nbd.c | 10 +-
qtest.c | 2 +-
target/xtensa/xtensa-semi.c | 2 +-
tests/test-char.c | 275 ++++++++++++++++++++++++++++----------
tests/test-hmp.c | 1 +
tests/vhost-user-test.c | 2 +-
vl.c | 8 +-
97 files changed, 1831 insertions(+), 643 deletions(-)
--
1.8.3.1
^ permalink raw reply [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 01/41] build: add -Wexpansion-to-defined
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
@ 2017-07-13 14:23 ` Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 02/41] MAINTAINERS: update TCG entries Paolo Bonzini
` (40 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:23 UTC (permalink / raw)
To: qemu-devel
This warning is included in -Wall by clang, but not by GCC (which only
enables it for -Wextra). Include it in the list of warnings we enable
to minimize the differences between the compilers:
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
configure | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configure b/configure
index 5096cbc..239f142 100755
--- a/configure
+++ b/configure
@@ -1583,7 +1583,7 @@ gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
gcc_flags="-Wno-missing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
gcc_flags="-Wendif-labels -Wno-shift-negative-value $gcc_flags"
-gcc_flags="-Wno-initializer-overrides $gcc_flags"
+gcc_flags="-Wno-initializer-overrides -Wexpansion-to-defined $gcc_flags"
gcc_flags="-Wno-string-plus-int $gcc_flags"
# Note that we do not add -Werror to gcc_flags here, because that would
# enable it for all configure tests. If a configure test failed due
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 02/41] MAINTAINERS: update TCG entries
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 01/41] build: add -Wexpansion-to-defined Paolo Bonzini
@ 2017-07-13 14:23 ` Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 03/41] MAINTAINERS: update KVM entries Paolo Bonzini
` (39 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:23 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
moved in a9ded601..244f1441 to accel/
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170629150308.22766-2-f4bug@amsat.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
MAINTAINERS | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 9529c94..74b3956 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -84,14 +84,10 @@ M: Paolo Bonzini <pbonzini@redhat.com>
M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
M: Richard Henderson <rth@twiddle.net>
S: Maintained
-F: cpu-exec.c
-F: cpu-exec-common.c
F: cpus.c
-F: cputlb.c
F: exec.c
F: softmmu_template.h
-F: translate-all.*
-F: translate-common.c
+F: accel/tcg/
F: include/exec/cpu*.h
F: include/exec/exec-all.h
F: include/exec/helper*.h
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 03/41] MAINTAINERS: update KVM entries
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 01/41] build: add -Wexpansion-to-defined Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 02/41] MAINTAINERS: update TCG entries Paolo Bonzini
@ 2017-07-13 14:23 ` Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 04/41] MAINTAINERS: update Xen entries Paolo Bonzini
` (38 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:23 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
moved in 92229a57 to accel/
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170629150308.22766-3-f4bug@amsat.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
MAINTAINERS | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 74b3956..55061e9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -273,8 +273,8 @@ Overall
M: Paolo Bonzini <pbonzini@redhat.com>
L: kvm@vger.kernel.org
S: Supported
-F: kvm-*
F: */kvm.*
+F: accel/kvm/
F: include/sysemu/kvm*.h
ARM
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 04/41] MAINTAINERS: update Xen entries
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (2 preceding siblings ...)
2017-07-13 14:23 ` [Qemu-devel] [PULL 03/41] MAINTAINERS: update KVM entries Paolo Bonzini
@ 2017-07-13 14:23 ` Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 05/41] MAINTAINERS: update TCI entry Paolo Bonzini
` (37 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:23 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
moved in 56e2cd24..28b99f47 to hw/xen/ and hw/i386/xen/
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Message-Id: <20170629150308.22766-4-f4bug@amsat.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
MAINTAINERS | 1 -
1 file changed, 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 55061e9..5540460 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -323,7 +323,6 @@ M: Stefano Stabellini <sstabellini@kernel.org>
M: Anthony Perard <anthony.perard@citrix.com>
L: xen-devel@lists.xenproject.org
S: Supported
-F: xen-*
F: */xen*
F: hw/9pfs/xen-9p-backend.c
F: hw/char/xen_console.c
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 05/41] MAINTAINERS: update TCI entry
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (3 preceding siblings ...)
2017-07-13 14:23 ` [Qemu-devel] [PULL 04/41] MAINTAINERS: update Xen entries Paolo Bonzini
@ 2017-07-13 14:23 ` Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 06/41] MAINTAINERS: add entry for "Unimplemented" device Paolo Bonzini
` (36 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:23 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
moved in 244f1441 to tcg/
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170629150308.22766-5-f4bug@amsat.org>
Reviewed-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
MAINTAINERS | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 5540460..dd7e1e5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1645,7 +1645,7 @@ TCI target
M: Stefan Weil <sw@weilnetz.de>
S: Maintained
F: tcg/tci/
-F: tci.c
+F: tcg/tci.c
F: disas/tci.c
Block drivers
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 06/41] MAINTAINERS: add entry for "Unimplemented" device
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (4 preceding siblings ...)
2017-07-13 14:23 ` [Qemu-devel] [PULL 05/41] MAINTAINERS: update TCI entry Paolo Bonzini
@ 2017-07-13 14:23 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 07/41] chardev: block during sync read Paolo Bonzini
` (35 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:23 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
Also voluntary myself as reviewer
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170629150308.22766-6-f4bug@amsat.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
MAINTAINERS | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index dd7e1e5..b9aa878 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1155,6 +1155,13 @@ F: docs/specs/vmgenid.txt
F: tests/vmgenid-test.c
F: stubs/vmgenid.c
+Unimplemented device
+M: Peter Maydell <peter.maydell@linaro.org>
+R: Philippe Mathieu-Daudé <f4bug@amsat.org>
+S: Maintained
+F: include/hw/misc/unimp.h
+F: hw/misc/unimp.c
+
Subsystems
----------
Audio
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 07/41] chardev: block during sync read
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (5 preceding siblings ...)
2017-07-13 14:23 ` [Qemu-devel] [PULL 06/41] MAINTAINERS: add entry for "Unimplemented" device Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 08/41] char: move QemuOpts->ChardevBackend translation to a separate func Paolo Bonzini
` (34 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
From: Marc-André Lureau <marcandre.lureau@redhat.com>
A sync read should block until all requested data is
available (instead of retrying in qemu_chr_fe_read_all). Change the
channel to blocking during sync_read.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20170706170353.32601-1-marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
chardev/char-socket.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index ccc499c..7e6648b 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -454,7 +454,9 @@ static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
return 0;
}
+ qio_channel_set_blocking(s->ioc, true, NULL);
size = tcp_chr_recv(chr, (void *) buf, len);
+ qio_channel_set_blocking(s->ioc, false, NULL);
if (size == 0) {
/* connection closed */
tcp_chr_disconnect(chr);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 08/41] char: move QemuOpts->ChardevBackend translation to a separate func
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (6 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 07/41] chardev: block during sync read Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 09/41] char: add backend hotswap handler Paolo Bonzini
` (33 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
parse function will be used by the following patch
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Message-Id: <1499342940-56739-2-git-send-email-anton.nefedov@virtuozzo.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
chardev/char.c | 81 ++++++++++++++++++++++++++++++++++++----------------------
1 file changed, 51 insertions(+), 30 deletions(-)
diff --git a/chardev/char.c b/chardev/char.c
index 2b679a2..839eff6 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -556,17 +556,23 @@ help_string_append(const char *name, void *opaque)
g_string_append_printf(str, "\n%s", name);
}
-Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
- Error **errp)
+static const char *chardev_alias_translate(const char *name)
+{
+ int i;
+ for (i = 0; i < (int)ARRAY_SIZE(chardev_alias_table); i++) {
+ if (g_strcmp0(chardev_alias_table[i].alias, name) == 0) {
+ return chardev_alias_table[i].typename;
+ }
+ }
+ return name;
+}
+
+static ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts, Error **errp)
{
Error *local_err = NULL;
const ChardevClass *cc;
- Chardev *chr;
- int i;
ChardevBackend *backend = NULL;
- const char *name = qemu_opt_get(opts, "backend");
- const char *id = qemu_opts_id(opts);
- char *bid = NULL;
+ const char *name = chardev_alias_translate(qemu_opt_get(opts, "backend"));
if (name == NULL) {
error_setg(errp, "chardev: \"%s\" missing backend",
@@ -574,7 +580,40 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
return NULL;
}
- if (is_help_option(name)) {
+ cc = char_get_class(name, errp);
+ if (cc == NULL) {
+ return NULL;
+ }
+
+ backend = g_new0(ChardevBackend, 1);
+ backend->type = CHARDEV_BACKEND_KIND_NULL;
+
+ if (cc->parse) {
+ cc->parse(opts, backend, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ qapi_free_ChardevBackend(backend);
+ return NULL;
+ }
+ } else {
+ ChardevCommon *ccom = g_new0(ChardevCommon, 1);
+ qemu_chr_parse_common(opts, ccom);
+ backend->u.null.data = ccom; /* Any ChardevCommon member would work */
+ }
+
+ return backend;
+}
+
+Chardev *qemu_chr_new_from_opts(QemuOpts *opts, Error **errp)
+{
+ const ChardevClass *cc;
+ Chardev *chr = NULL;
+ ChardevBackend *backend = NULL;
+ const char *name = chardev_alias_translate(qemu_opt_get(opts, "backend"));
+ const char *id = qemu_opts_id(opts);
+ char *bid = NULL;
+
+ if (name && is_help_option(name)) {
GString *str = g_string_new("");
chardev_name_foreach(help_string_append, str);
@@ -589,38 +628,20 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
return NULL;
}
- for (i = 0; i < (int)ARRAY_SIZE(chardev_alias_table); i++) {
- if (g_strcmp0(chardev_alias_table[i].alias, name) == 0) {
- name = chardev_alias_table[i].typename;
- break;
- }
+ backend = qemu_chr_parse_opts(opts, errp);
+ if (backend == NULL) {
+ return NULL;
}
cc = char_get_class(name, errp);
if (cc == NULL) {
- return NULL;
+ goto out;
}
- backend = g_new0(ChardevBackend, 1);
- backend->type = CHARDEV_BACKEND_KIND_NULL;
-
if (qemu_opt_get_bool(opts, "mux", 0)) {
bid = g_strdup_printf("%s-base", id);
}
- chr = NULL;
- if (cc->parse) {
- cc->parse(opts, backend, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- goto out;
- }
- } else {
- ChardevCommon *ccom = g_new0(ChardevCommon, 1);
- qemu_chr_parse_common(opts, ccom);
- backend->u.null.data = ccom; /* Any ChardevCommon member would work */
- }
-
chr = qemu_chardev_new(bid ? bid : id,
object_class_get_name(OBJECT_CLASS(cc)),
backend, errp);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 09/41] char: add backend hotswap handler
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (7 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 08/41] char: move QemuOpts->ChardevBackend translation to a separate func Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 10/41] char: chardevice hotswap Paolo Bonzini
` (32 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
Frontends should have an interface to setup the handler of a backend change.
The interface will be used in the next commits
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1499342940-56739-3-git-send-email-anton.nefedov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
backends/rng-egd.c | 2 +-
chardev/char-fe.c | 4 +++-
chardev/char-mux.c | 1 +
gdbstub.c | 2 +-
hw/arm/pxa2xx.c | 3 ++-
hw/arm/strongarm.c | 2 +-
hw/char/bcm2835_aux.c | 2 +-
hw/char/cadence_uart.c | 2 +-
hw/char/debugcon.c | 2 +-
hw/char/digic-uart.c | 2 +-
hw/char/escc.c | 2 +-
hw/char/etraxfs_ser.c | 2 +-
hw/char/exynos4210_uart.c | 2 +-
hw/char/grlib_apbuart.c | 2 +-
hw/char/imx_serial.c | 2 +-
hw/char/ipoctal232.c | 2 +-
hw/char/lm32_juart.c | 2 +-
hw/char/lm32_uart.c | 2 +-
hw/char/mcf_uart.c | 2 +-
hw/char/milkymist-uart.c | 2 +-
hw/char/pl011.c | 2 +-
hw/char/sclpconsole-lm.c | 2 +-
hw/char/sclpconsole.c | 2 +-
hw/char/serial.c | 2 +-
hw/char/sh_serial.c | 2 +-
hw/char/spapr_vty.c | 2 +-
hw/char/stm32f2xx_usart.c | 3 ++-
hw/char/terminal3270.c | 2 +-
hw/char/virtio-console.c | 4 ++--
hw/char/xen_console.c | 2 +-
hw/char/xilinx_uartlite.c | 2 +-
hw/ipmi/ipmi_bmc_extern.c | 2 +-
hw/mips/boston.c | 2 +-
hw/mips/mips_malta.c | 2 +-
hw/misc/ivshmem.c | 2 +-
hw/usb/ccid-card-passthru.c | 2 +-
hw/usb/dev-serial.c | 2 +-
hw/usb/redirect.c | 2 +-
include/chardev/char-fe.h | 5 +++++
monitor.c | 4 ++--
net/colo-compare.c | 10 ++++++----
net/filter-mirror.c | 6 +++---
net/slirp.c | 2 +-
net/vhost-user.c | 7 ++++---
qtest.c | 2 +-
target/xtensa/xtensa-semi.c | 2 +-
tests/test-char.c | 14 ++++++++++----
tests/vhost-user-test.c | 2 +-
48 files changed, 77 insertions(+), 58 deletions(-)
diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index e7ce2ca..d2b9ce6 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -106,7 +106,7 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
/* FIXME we should resubmit pending requests when the CDS reconnects. */
qemu_chr_fe_set_handlers(&s->chr, rng_egd_chr_can_read,
- rng_egd_chr_read, NULL, s, NULL, true);
+ rng_egd_chr_read, NULL, NULL, s, NULL, true);
}
static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)
diff --git a/chardev/char-fe.c b/chardev/char-fe.c
index 3f90f05..7054863 100644
--- a/chardev/char-fe.c
+++ b/chardev/char-fe.c
@@ -216,7 +216,7 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del)
assert(b);
if (b->chr) {
- qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, true);
+ qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, NULL, true);
if (b->chr->be == b) {
b->chr->be = NULL;
}
@@ -235,6 +235,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
+ BackendChangeHandler *be_change,
void *opaque,
GMainContext *context,
bool set_open)
@@ -258,6 +259,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
b->chr_can_read = fd_can_read;
b->chr_read = fd_read;
b->chr_event = fd_event;
+ b->chr_be_change = be_change;
b->opaque = opaque;
if (cc->chr_update_read_handler) {
cc->chr_update_read_handler(s, context);
diff --git a/chardev/char-mux.c b/chardev/char-mux.c
index 08570b9..4cda5e7 100644
--- a/chardev/char-mux.c
+++ b/chardev/char-mux.c
@@ -278,6 +278,7 @@ void mux_chr_set_handlers(Chardev *chr, GMainContext *context)
mux_chr_can_read,
mux_chr_read,
mux_chr_event,
+ NULL,
chr,
context, true);
}
diff --git a/gdbstub.c b/gdbstub.c
index ec4e4b2..e561244 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2003,7 +2003,7 @@ int gdbserver_start(const char *device)
if (chr) {
qemu_chr_fe_init(&s->chr, chr, &error_abort);
qemu_chr_fe_set_handlers(&s->chr, gdb_chr_can_receive, gdb_chr_receive,
- gdb_chr_event, NULL, NULL, true);
+ gdb_chr_event, NULL, NULL, NULL, true);
}
s->state = chr ? RS_IDLE : RS_INACTIVE;
s->mon_chr = mon_chr;
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 629e6c6..731ed08 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1970,7 +1970,8 @@ static void pxa2xx_fir_realize(DeviceState *dev, Error **errp)
PXA2xxFIrState *s = PXA2XX_FIR(dev);
qemu_chr_fe_set_handlers(&s->chr, pxa2xx_fir_is_empty,
- pxa2xx_fir_rx, pxa2xx_fir_event, s, NULL, true);
+ pxa2xx_fir_rx, pxa2xx_fir_event, NULL, s, NULL,
+ true);
}
static bool pxa2xx_fir_vmstate_validate(void *opaque, int version_id)
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index 7683edc..1fa082c 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -1247,7 +1247,7 @@ static void strongarm_uart_realize(DeviceState *dev, Error **errp)
strongarm_uart_can_receive,
strongarm_uart_receive,
strongarm_uart_event,
- s, NULL, true);
+ NULL, s, NULL, true);
}
static void strongarm_uart_reset(DeviceState *dev)
diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c
index 4d46ad6..370dc7e 100644
--- a/hw/char/bcm2835_aux.c
+++ b/hw/char/bcm2835_aux.c
@@ -279,7 +279,7 @@ static void bcm2835_aux_realize(DeviceState *dev, Error **errp)
BCM2835AuxState *s = BCM2835_AUX(dev);
qemu_chr_fe_set_handlers(&s->chr, bcm2835_aux_can_receive,
- bcm2835_aux_receive, NULL, s, NULL, true);
+ bcm2835_aux_receive, NULL, NULL, s, NULL, true);
}
static Property bcm2835_aux_props[] = {
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 4a2c124..3a9335c 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -485,7 +485,7 @@ static void cadence_uart_realize(DeviceState *dev, Error **errp)
fifo_trigger_update, s);
qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
- uart_event, s, NULL, true);
+ uart_event, NULL, s, NULL, true);
}
static void cadence_uart_init(Object *obj)
diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
index 762e3d8..9b56fb8 100644
--- a/hw/char/debugcon.c
+++ b/hw/char/debugcon.c
@@ -92,7 +92,7 @@ static void debugcon_realize_core(DebugconState *s, Error **errp)
return;
}
- qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, s, NULL, true);
+ qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, NULL, s, NULL, true);
}
static void debugcon_isa_realizefn(DeviceState *dev, Error **errp)
diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c
index 34306e1..6ebcb87 100644
--- a/hw/char/digic-uart.c
+++ b/hw/char/digic-uart.c
@@ -146,7 +146,7 @@ static void digic_uart_realize(DeviceState *dev, Error **errp)
DigicUartState *s = DIGIC_UART(dev);
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
- uart_event, s, NULL, true);
+ uart_event, NULL, s, NULL, true);
}
static void digic_uart_init(Object *obj)
diff --git a/hw/char/escc.c b/hw/char/escc.c
index 3f78763..3546df3 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -1016,7 +1016,7 @@ static void escc_realize(DeviceState *dev, Error **errp)
if (qemu_chr_fe_get_driver(&s->chn[i].chr)) {
s->chn[i].clock = s->frequency / 2;
qemu_chr_fe_set_handlers(&s->chn[i].chr, serial_can_receive,
- serial_receive1, serial_event,
+ serial_receive1, serial_event, NULL,
&s->chn[i], NULL, true);
}
}
diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
index c1fba9f..a184026 100644
--- a/hw/char/etraxfs_ser.c
+++ b/hw/char/etraxfs_ser.c
@@ -233,7 +233,7 @@ static void etraxfs_ser_realize(DeviceState *dev, Error **errp)
qemu_chr_fe_set_handlers(&s->chr,
serial_can_receive, serial_receive,
- serial_event, s, NULL, true);
+ serial_event, NULL, s, NULL, true);
}
static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index b51d44a..a84d2c3 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -645,7 +645,7 @@ static void exynos4210_uart_realize(DeviceState *dev, Error **errp)
qemu_chr_fe_set_handlers(&s->chr, exynos4210_uart_can_receive,
exynos4210_uart_receive, exynos4210_uart_event,
- s, NULL, true);
+ NULL, s, NULL, true);
}
static Property exynos4210_uart_properties[] = {
diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
index 32d98ed..12d0c99 100644
--- a/hw/char/grlib_apbuart.c
+++ b/hw/char/grlib_apbuart.c
@@ -247,7 +247,7 @@ static int grlib_apbuart_init(SysBusDevice *dev)
grlib_apbuart_can_receive,
grlib_apbuart_receive,
grlib_apbuart_event,
- uart, NULL, true);
+ NULL, uart, NULL, true);
sysbus_init_irq(dev, &uart->irq);
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index af25030..70405cc 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -315,7 +315,7 @@ static void imx_serial_realize(DeviceState *dev, Error **errp)
DPRINTF("char dev for uart: %p\n", qemu_chr_fe_get_driver(&s->chr));
qemu_chr_fe_set_handlers(&s->chr, imx_can_receive, imx_receive,
- imx_event, s, NULL, true);
+ imx_event, NULL, s, NULL, true);
}
static void imx_serial_init(Object *obj)
diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c
index 337a3e56..cc8c8dc 100644
--- a/hw/char/ipoctal232.c
+++ b/hw/char/ipoctal232.c
@@ -545,7 +545,7 @@ static void ipoctal_realize(DeviceState *dev, Error **errp)
if (qemu_chr_fe_get_driver(&ch->dev)) {
qemu_chr_fe_set_handlers(&ch->dev, hostdev_can_receive,
hostdev_receive, hostdev_event,
- ch, NULL, true);
+ NULL, ch, NULL, true);
DPRINTF("Redirecting channel %u to %s\n", i, ch->dev->label);
} else {
DPRINTF("Could not redirect channel %u, no chardev set\n", i);
diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c
index 3948dcd..d75c835 100644
--- a/hw/char/lm32_juart.c
+++ b/hw/char/lm32_juart.c
@@ -119,7 +119,7 @@ static void lm32_juart_realize(DeviceState *dev, Error **errp)
LM32JuartState *s = LM32_JUART(dev);
qemu_chr_fe_set_handlers(&s->chr, juart_can_rx, juart_rx,
- juart_event, s, NULL, true);
+ juart_event, NULL, s, NULL, true);
}
static const VMStateDescription vmstate_lm32_juart = {
diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c
index cff8c38..c4a3b9b 100644
--- a/hw/char/lm32_uart.c
+++ b/hw/char/lm32_uart.c
@@ -266,7 +266,7 @@ static void lm32_uart_realize(DeviceState *dev, Error **errp)
LM32UartState *s = LM32_UART(dev);
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
- uart_event, s, NULL, true);
+ uart_event, NULL, s, NULL, true);
}
static const VMStateDescription vmstate_lm32_uart = {
diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c
index fe12ad5..56fa402 100644
--- a/hw/char/mcf_uart.c
+++ b/hw/char/mcf_uart.c
@@ -305,7 +305,7 @@ static void mcf_uart_realize(DeviceState *dev, Error **errp)
mcf_uart_state *s = MCF_UART(dev);
qemu_chr_fe_set_handlers(&s->chr, mcf_uart_can_receive, mcf_uart_receive,
- mcf_uart_event, s, NULL, true);
+ mcf_uart_event, NULL, s, NULL, true);
}
static Property mcf_uart_properties[] = {
diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c
index e19d0f6..548ee27 100644
--- a/hw/char/milkymist-uart.c
+++ b/hw/char/milkymist-uart.c
@@ -199,7 +199,7 @@ static void milkymist_uart_realize(DeviceState *dev, Error **errp)
MilkymistUartState *s = MILKYMIST_UART(dev);
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
- uart_event, s, NULL, true);
+ uart_event, NULL, s, NULL, true);
}
static void milkymist_uart_init(Object *obj)
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 33802f0..2aa277f 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -329,7 +329,7 @@ static void pl011_realize(DeviceState *dev, Error **errp)
PL011State *s = PL011(dev);
qemu_chr_fe_set_handlers(&s->chr, pl011_can_receive, pl011_receive,
- pl011_event, s, NULL, true);
+ pl011_event, NULL, s, NULL, true);
}
static void pl011_class_init(ObjectClass *oc, void *data)
diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index 1b15046..741c641 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -313,7 +313,7 @@ static int console_init(SCLPEvent *event)
console_available = true;
qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
- chr_read, NULL, scon, NULL, true);
+ chr_read, NULL, NULL, scon, NULL, true);
return 0;
}
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index 4a107a2..a92baa8 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -228,7 +228,7 @@ static int console_init(SCLPEvent *event)
}
console_available = true;
qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
- chr_read, NULL, scon, NULL, true);
+ chr_read, NULL, NULL, scon, NULL, true);
return 0;
}
diff --git a/hw/char/serial.c b/hw/char/serial.c
index e1f1250..ab14ca4 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -897,7 +897,7 @@ void serial_realize_core(SerialState *s, Error **errp)
qemu_register_reset(serial_reset, s);
qemu_chr_fe_set_handlers(&s->chr, serial_can_receive1, serial_receive1,
- serial_event, s, NULL, true);
+ serial_event, NULL, s, NULL, true);
fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
serial_reset(s);
diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c
index ca9816d..ad043bd 100644
--- a/hw/char/sh_serial.c
+++ b/hw/char/sh_serial.c
@@ -400,7 +400,7 @@ void sh_serial_init(MemoryRegion *sysmem,
qemu_chr_fe_init(&s->chr, chr, &error_abort);
qemu_chr_fe_set_handlers(&s->chr, sh_serial_can_receive1,
sh_serial_receive1,
- sh_serial_event, s, NULL, true);
+ sh_serial_event, NULL, s, NULL, true);
}
s->eri = eri_source;
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
index 8f02f3a..ddd1b00 100644
--- a/hw/char/spapr_vty.c
+++ b/hw/char/spapr_vty.c
@@ -84,7 +84,7 @@ static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp)
}
qemu_chr_fe_set_handlers(&dev->chardev, vty_can_receive,
- vty_receive, NULL, dev, NULL, true);
+ vty_receive, NULL, NULL, dev, NULL, true);
}
/* Forward declaration */
diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c
index 59872e6..268e435 100644
--- a/hw/char/stm32f2xx_usart.c
+++ b/hw/char/stm32f2xx_usart.c
@@ -207,7 +207,8 @@ static void stm32f2xx_usart_realize(DeviceState *dev, Error **errp)
STM32F2XXUsartState *s = STM32F2XX_USART(dev);
qemu_chr_fe_set_handlers(&s->chr, stm32f2xx_usart_can_receive,
- stm32f2xx_usart_receive, NULL, s, NULL, true);
+ stm32f2xx_usart_receive, NULL, NULL,
+ s, NULL, true);
}
static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)
diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c
index 7b10a04..5adf95b 100644
--- a/hw/char/terminal3270.c
+++ b/hw/char/terminal3270.c
@@ -179,7 +179,7 @@ static void terminal_init(EmulatedCcw3270Device *dev, Error **errp)
}
terminal_available = true;
qemu_chr_fe_set_handlers(&t->chr, terminal_can_read,
- terminal_read, chr_event, t, NULL, true);
+ terminal_read, chr_event, NULL, t, NULL, true);
}
static int read_payload_3270(EmulatedCcw3270Device *dev, uint32_t cda,
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index 0cb1668..afb4949 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -188,11 +188,11 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
*/
if (k->is_console) {
qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
- NULL, vcon, NULL, true);
+ NULL, NULL, vcon, NULL, true);
virtio_serial_open(port);
} else {
qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
- chr_event, vcon, NULL, false);
+ chr_event, NULL, vcon, NULL, false);
}
}
}
diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c
index f9af8ca..c4e8c72 100644
--- a/hw/char/xen_console.c
+++ b/hw/char/xen_console.c
@@ -246,7 +246,7 @@ static int con_initialise(struct XenDevice *xendev)
xen_be_bind_evtchn(&con->xendev);
qemu_chr_fe_set_handlers(&con->chr, xencons_can_receive,
- xencons_receive, NULL, con, NULL, true);
+ xencons_receive, NULL, NULL, con, NULL, true);
xen_pv_printf(xendev, 1,
"ring mfn %d, remote port %d, local port %d, limit %zd\n",
diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
index 71ed2fc..2a8bc1e 100644
--- a/hw/char/xilinx_uartlite.c
+++ b/hw/char/xilinx_uartlite.c
@@ -212,7 +212,7 @@ static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
XilinxUARTLite *s = XILINX_UARTLITE(dev);
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
- uart_event, s, NULL, true);
+ uart_event, NULL, s, NULL, true);
}
static void xilinx_uartlite_init(Object *obj)
diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c
index 329b03e..182de58 100644
--- a/hw/ipmi/ipmi_bmc_extern.c
+++ b/hw/ipmi/ipmi_bmc_extern.c
@@ -453,7 +453,7 @@ static void ipmi_bmc_extern_realize(DeviceState *dev, Error **errp)
}
qemu_chr_fe_set_handlers(&ibe->chr, can_receive, receive,
- chr_event, ibe, NULL, true);
+ chr_event, NULL, ibe, NULL, true);
}
static int ipmi_bmc_extern_post_migrate(void *opaque, int version_id)
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
index a4677f7..146be2a 100644
--- a/hw/mips/boston.c
+++ b/hw/mips/boston.c
@@ -533,7 +533,7 @@ static void boston_mach_init(MachineState *machine)
chr = qemu_chr_new("lcd", "vc:320x240");
qemu_chr_fe_init(&s->lcd_display, chr, NULL);
qemu_chr_fe_set_handlers(&s->lcd_display, NULL, NULL,
- boston_lcd_event, s, NULL, true);
+ boston_lcd_event, NULL, s, NULL, true);
ahci = pci_create_simple_multifunction(&PCI_BRIDGE(&pcie2->root)->sec_bus,
PCI_DEVFN(0, 0),
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index dad2f37..8cb9d3c 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -570,7 +570,7 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
chr = qemu_chr_new("fpga", "vc:320x200");
qemu_chr_fe_init(&s->display, chr, NULL);
qemu_chr_fe_set_handlers(&s->display, NULL, NULL,
- malta_fgpa_display_event, s, NULL, true);
+ malta_fgpa_display_event, NULL, s, NULL, true);
s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
230400, uart_chr, DEVICE_NATIVE_ENDIAN);
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 2f0819d..a857e50 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -894,7 +894,7 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
}
qemu_chr_fe_set_handlers(&s->server_chr, ivshmem_can_receive,
- ivshmem_read, NULL, s, NULL, true);
+ ivshmem_read, NULL, NULL, s, NULL, true);
if (ivshmem_setup_interrupts(s, errp) < 0) {
error_prepend(errp, "Failed to initialize interrupts: ");
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index ac1725e..e9f58c9 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -348,7 +348,7 @@ static int passthru_initfn(CCIDCardState *base)
qemu_chr_fe_set_handlers(&card->cs,
ccid_card_vscard_can_read,
ccid_card_vscard_read,
- ccid_card_vscard_event, card, NULL, true);
+ ccid_card_vscard_event, NULL, card, NULL, true);
ccid_card_vscard_send_init(card);
} else {
error_report("missing chardev");
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index bfbf7cd..dc145a6 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -502,7 +502,7 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
}
qemu_chr_fe_set_handlers(&s->cs, usb_serial_can_read, usb_serial_read,
- usb_serial_event, s, NULL, true);
+ usb_serial_event, NULL, s, NULL, true);
usb_serial_handle_reset(dev);
if (chr->be_open && !dev->attached) {
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index aa22d69..115efb9 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1399,7 +1399,7 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
/* Let the backend know we are ready */
qemu_chr_fe_set_handlers(&dev->cs, usbredir_chardev_can_read,
usbredir_chardev_read, usbredir_chardev_event,
- dev, NULL, true);
+ NULL, dev, NULL, true);
dev->vmstate =
qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev);
diff --git a/include/chardev/char-fe.h b/include/chardev/char-fe.h
index 2cbb262..9f38060 100644
--- a/include/chardev/char-fe.h
+++ b/include/chardev/char-fe.h
@@ -4,6 +4,7 @@
#include "chardev/char.h"
typedef void IOEventHandler(void *opaque, int event);
+typedef int BackendChangeHandler(void *opaque);
/* This is the backend as seen by frontend, the actual backend is
* Chardev */
@@ -12,6 +13,7 @@ struct CharBackend {
IOEventHandler *chr_event;
IOCanReadHandler *chr_can_read;
IOReadHandler *chr_read;
+ BackendChangeHandler *chr_be_change;
void *opaque;
int tag;
int fe_open;
@@ -54,6 +56,8 @@ Chardev *qemu_chr_fe_get_driver(CharBackend *be);
* receive
* @fd_read: callback to receive data from char
* @fd_event: event callback
+ * @be_change: backend change callback; passing NULL means hot backend change
+ * is not supported and will not be attempted
* @opaque: an opaque pointer for the callbacks
* @context: a main loop context or NULL for the default
* @set_open: whether to call qemu_chr_fe_set_open() implicitely when
@@ -68,6 +72,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
+ BackendChangeHandler *be_change,
void *opaque,
GMainContext *context,
bool set_open);
diff --git a/monitor.c b/monitor.c
index d8ac20f..292fc34 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4110,12 +4110,12 @@ void monitor_init(Chardev *chr, int flags)
if (monitor_is_qmp(mon)) {
qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_qmp_read,
- monitor_qmp_event, mon, NULL, true);
+ monitor_qmp_event, NULL, mon, NULL, true);
qemu_chr_fe_set_echo(&mon->chr, true);
json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
} else {
qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_read,
- monitor_event, mon, NULL, true);
+ monitor_event, NULL, mon, NULL, true);
}
qemu_mutex_lock(&monitor_lock);
diff --git a/net/colo-compare.c b/net/colo-compare.c
index 6d500e1..abfc23c 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -543,7 +543,7 @@ static void compare_pri_chr_in(void *opaque, const uint8_t *buf, int size)
ret = net_fill_rstate(&s->pri_rs, buf, size);
if (ret == -1) {
- qemu_chr_fe_set_handlers(&s->chr_pri_in, NULL, NULL, NULL,
+ qemu_chr_fe_set_handlers(&s->chr_pri_in, NULL, NULL, NULL, NULL,
NULL, NULL, true);
error_report("colo-compare primary_in error");
}
@@ -560,7 +560,7 @@ static void compare_sec_chr_in(void *opaque, const uint8_t *buf, int size)
ret = net_fill_rstate(&s->sec_rs, buf, size);
if (ret == -1) {
- qemu_chr_fe_set_handlers(&s->chr_sec_in, NULL, NULL, NULL,
+ qemu_chr_fe_set_handlers(&s->chr_sec_in, NULL, NULL, NULL, NULL,
NULL, NULL, true);
error_report("colo-compare secondary_in error");
}
@@ -588,9 +588,11 @@ static void *colo_compare_thread(void *opaque)
s->worker_context = g_main_context_new();
qemu_chr_fe_set_handlers(&s->chr_pri_in, compare_chr_can_read,
- compare_pri_chr_in, NULL, s, s->worker_context, true);
+ compare_pri_chr_in, NULL, NULL,
+ s, s->worker_context, true);
qemu_chr_fe_set_handlers(&s->chr_sec_in, compare_chr_can_read,
- compare_sec_chr_in, NULL, s, s->worker_context, true);
+ compare_sec_chr_in, NULL, NULL,
+ s, s->worker_context, true);
s->compare_loop = g_main_loop_new(s->worker_context, FALSE);
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index 52d978f..62a8265 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -112,7 +112,7 @@ static void redirector_chr_read(void *opaque, const uint8_t *buf, int size)
if (ret == -1) {
qemu_chr_fe_set_handlers(&s->chr_in, NULL, NULL, NULL,
- NULL, NULL, true);
+ NULL, NULL, NULL, true);
}
}
@@ -124,7 +124,7 @@ static void redirector_chr_event(void *opaque, int event)
switch (event) {
case CHR_EVENT_CLOSED:
qemu_chr_fe_set_handlers(&s->chr_in, NULL, NULL, NULL,
- NULL, NULL, true);
+ NULL, NULL, NULL, true);
break;
default:
break;
@@ -245,7 +245,7 @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp)
qemu_chr_fe_set_handlers(&s->chr_in, redirector_chr_can_read,
redirector_chr_read, redirector_chr_event,
- nf, NULL, true);
+ NULL, nf, NULL, true);
}
if (s->outdev) {
diff --git a/net/slirp.c b/net/slirp.c
index 6a6d727..9fbc949 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -778,7 +778,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
fwd->slirp = s->slirp;
qemu_chr_fe_set_handlers(&fwd->hd, guestfwd_can_read, guestfwd_read,
- NULL, fwd, NULL, true);
+ NULL, NULL, fwd, NULL, true);
}
return 0;
diff --git a/net/vhost-user.c b/net/vhost-user.c
index a042ec6..36f32a2 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -211,7 +211,7 @@ static void chr_closed_bh(void *opaque)
vhost_user_stop(queues, ncs);
qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event,
- opaque, NULL, true);
+ NULL, opaque, NULL, true);
if (err) {
error_report_err(err);
@@ -257,7 +257,7 @@ static void net_vhost_user_event(void *opaque, int event)
g_source_remove(s->watch);
s->watch = 0;
- qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL,
+ qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, NULL,
NULL, NULL, false);
aio_bh_schedule_oneshot(ctx, chr_closed_bh, opaque);
@@ -305,7 +305,8 @@ static int net_vhost_user_init(NetClientState *peer, const char *device,
return -1;
}
qemu_chr_fe_set_handlers(&s->chr, NULL, NULL,
- net_vhost_user_event, nc0->name, NULL, true);
+ net_vhost_user_event, NULL, nc0->name, NULL,
+ true);
} while (!s->started);
assert(s->vhost_net);
diff --git a/qtest.c b/qtest.c
index 9a5d1dc..88a09e9 100644
--- a/qtest.c
+++ b/qtest.c
@@ -691,7 +691,7 @@ void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
qemu_chr_fe_init(&qtest_chr, chr, errp);
qemu_chr_fe_set_handlers(&qtest_chr, qtest_can_read, qtest_read,
- qtest_event, &qtest_chr, NULL, true);
+ qtest_event, NULL, &qtest_chr, NULL, true);
qemu_chr_fe_set_echo(&qtest_chr, true);
inbuf = g_string_new("");
diff --git a/target/xtensa/xtensa-semi.c b/target/xtensa/xtensa-semi.c
index 32e2bd7..7aa1d13 100644
--- a/target/xtensa/xtensa-semi.c
+++ b/target/xtensa/xtensa-semi.c
@@ -158,7 +158,7 @@ void xtensa_sim_open_console(Chardev *chr)
static CharBackend console;
qemu_chr_fe_init(&console, chr, &error_abort);
- qemu_chr_fe_set_handlers(&console, NULL, NULL, NULL, NULL, NULL, true);
+ qemu_chr_fe_set_handlers(&console, NULL, NULL, NULL, NULL, NULL, NULL, true);
xtensa_sim_console = &console;
}
diff --git a/tests/test-char.c b/tests/test-char.c
index b962063..38aaa27 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -178,6 +178,7 @@ static void char_mux_test(void)
fe_can_read,
fe_read,
fe_event,
+ NULL,
&h1,
NULL, true);
@@ -186,6 +187,7 @@ static void char_mux_test(void)
fe_can_read,
fe_read,
fe_event,
+ NULL,
&h2,
NULL, true);
qemu_chr_fe_take_focus(&chr_be2);
@@ -209,7 +211,8 @@ static void char_mux_test(void)
h1.read_count = 0;
/* remove first handler */
- qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL, NULL, true);
+ qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL,
+ NULL, NULL, true);
qemu_chr_be_write(base, (void *)"hello", 6);
g_assert_cmpint(h1.read_count, ==, 0);
g_assert_cmpint(h2.read_count, ==, 0);
@@ -307,13 +310,13 @@ static void char_socket_test(void)
qemu_chr_fe_init(&be, chr, &error_abort);
qemu_chr_fe_set_handlers(&be, socket_can_read, socket_read,
- NULL, &d, NULL, true);
+ NULL, NULL, &d, NULL, true);
chr_client = qemu_chr_new("client", tmp);
qemu_chr_fe_init(&client_be, chr_client, &error_abort);
qemu_chr_fe_set_handlers(&client_be, socket_can_read_hello,
socket_read_hello,
- NULL, &d, NULL, true);
+ NULL, NULL, &d, NULL, true);
g_free(tmp);
d.conn_expected = true;
@@ -383,6 +386,7 @@ static void char_pipe_test(void)
fe_can_read,
fe_read,
fe_event,
+ NULL,
&fe,
NULL, true);
@@ -431,7 +435,7 @@ static void char_udp_test(void)
d.chr = chr;
qemu_chr_fe_init(&be, chr, &error_abort);
qemu_chr_fe_set_handlers(&be, socket_can_read_hello, socket_read_hello,
- NULL, &d, NULL, true);
+ NULL, NULL, &d, NULL, true);
ret = qemu_chr_write_all(chr, (uint8_t *)"hello", 5);
g_assert_cmpint(ret, ==, 5);
@@ -523,6 +527,7 @@ static void char_file_test(void)
fe_can_read,
fe_read,
fe_event,
+ NULL,
&fe, NULL, true);
g_assert_cmpint(fe.last_event, !=, CHR_EVENT_BREAK);
@@ -583,6 +588,7 @@ static void char_null_test(void)
fe_can_read,
fe_read,
fe_event,
+ NULL,
NULL, NULL, true);
ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index b3cc045..d4da09f 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -464,7 +464,7 @@ static void test_server_create_chr(TestServer *server, const gchar *opt)
qemu_chr_fe_init(&server->chr, chr, &error_abort);
qemu_chr_fe_set_handlers(&server->chr, chr_can_read, chr_read,
- chr_event, server, NULL, true);
+ chr_event, NULL, server, NULL, true);
}
static void test_server_listen(TestServer *server)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 10/41] char: chardevice hotswap
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (8 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 09/41] char: add backend hotswap handler Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 11/41] char: forbid direct chardevice access for hotswap devices Paolo Bonzini
` (31 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
This patch adds a possibility to change a char device without a frontend
removal.
Ideally, it would have to happen transparently to a frontend, i.e.
frontend would continue its regular operation.
However, backends are not stateless and are set up by the frontends
via qemu_chr_fe_<> functions, and it's not (generally) possible to replay
that setup entirely in a backend code, as different chardevs respond
to the setup calls differently, so do frontends work differently basing
on those setup responses.
Moreover, some frontend can generally get and save the backend pointer
(qemu_chr_fe_get_driver()), and it will become invalid after backend change.
So, a frontend which would like to support chardev hotswap has to register
a "backend change" handler, and redo its backend setup there.
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <1499342940-56739-4-git-send-email-anton.nefedov@virtuozzo.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
chardev/char.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/chardev/char.h | 9 ++++++
qapi-schema.json | 40 ++++++++++++++++++++++++
3 files changed, 132 insertions(+)
diff --git a/chardev/char.c b/chardev/char.c
index 839eff6..d6b9d89 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -951,6 +951,89 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
return ret;
}
+ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend,
+ Error **errp)
+{
+ CharBackend *be;
+ const ChardevClass *cc;
+ Chardev *chr, *chr_new;
+ bool closed_sent = false;
+ ChardevReturn *ret;
+
+ chr = qemu_chr_find(id);
+ if (!chr) {
+ error_setg(errp, "Chardev '%s' does not exist", id);
+ return NULL;
+ }
+
+ if (CHARDEV_IS_MUX(chr)) {
+ error_setg(errp, "Mux device hotswap not supported yet");
+ return NULL;
+ }
+
+ if (qemu_chr_replay(chr)) {
+ error_setg(errp,
+ "Chardev '%s' cannot be changed in record/replay mode", id);
+ return NULL;
+ }
+
+ be = chr->be;
+ if (!be) {
+ /* easy case */
+ object_unparent(OBJECT(chr));
+ return qmp_chardev_add(id, backend, errp);
+ }
+
+ if (!be->chr_be_change) {
+ error_setg(errp, "Chardev user does not support chardev hotswap");
+ return NULL;
+ }
+
+ cc = char_get_class(ChardevBackendKind_lookup[backend->type], errp);
+ if (!cc) {
+ return NULL;
+ }
+
+ chr_new = qemu_chardev_new(NULL, object_class_get_name(OBJECT_CLASS(cc)),
+ backend, errp);
+ if (!chr_new) {
+ return NULL;
+ }
+ chr_new->label = g_strdup(id);
+
+ if (chr->be_open && !chr_new->be_open) {
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+ closed_sent = true;
+ }
+
+ chr->be = NULL;
+ qemu_chr_fe_init(be, chr_new, &error_abort);
+
+ if (be->chr_be_change(be->opaque) < 0) {
+ error_setg(errp, "Chardev '%s' change failed", chr_new->label);
+ chr_new->be = NULL;
+ qemu_chr_fe_init(be, chr, &error_abort);
+ if (closed_sent) {
+ qemu_chr_be_event(chr, CHR_EVENT_OPENED);
+ }
+ object_unref(OBJECT(chr_new));
+ return NULL;
+ }
+
+ object_unparent(OBJECT(chr));
+ object_property_add_child(get_chardevs_root(), chr_new->label,
+ OBJECT(chr_new), &error_abort);
+ object_unref(OBJECT(chr_new));
+
+ ret = g_new0(ChardevReturn, 1);
+ if (CHARDEV_IS_PTY(chr_new)) {
+ ret->pty = g_strdup(chr_new->filename + 4);
+ ret->has_pty = true;
+ }
+
+ return ret;
+}
+
void qmp_chardev_remove(const char *id, Error **errp)
{
Chardev *chr;
diff --git a/include/chardev/char.h b/include/chardev/char.h
index 8a9ade4..22fd734 100644
--- a/include/chardev/char.h
+++ b/include/chardev/char.h
@@ -93,6 +93,15 @@ void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend);
Chardev *qemu_chr_new(const char *label, const char *filename);
/**
+ * @qemu_chr_change:
+ *
+ * Change an existing character backend
+ *
+ * @opts the new backend options
+ */
+void qemu_chr_change(QemuOpts *opts, Error **errp);
+
+/**
* @qemu_chr_cleanup:
*
* Delete all chardevs (when leaving qemu)
diff --git a/qapi-schema.json b/qapi-schema.json
index 37c4b95..0090fbf 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -5098,6 +5098,46 @@
'returns': 'ChardevReturn' }
##
+# @chardev-change:
+#
+# Change a character device backend
+#
+# @id: the chardev's ID, must exist
+# @backend: new backend type and parameters
+#
+# Returns: ChardevReturn.
+#
+# Since: 2.10
+#
+# Example:
+#
+# -> { "execute" : "chardev-change",
+# "arguments" : { "id" : "baz",
+# "backend" : { "type" : "pty", "data" : {} } } }
+# <- { "return": { "pty" : "/dev/pty/42" } }
+#
+# -> {"execute" : "chardev-change",
+# "arguments" : {
+# "id" : "charchannel2",
+# "backend" : {
+# "type" : "socket",
+# "data" : {
+# "addr" : {
+# "type" : "unix" ,
+# "data" : {
+# "path" : "/tmp/charchannel2.socket"
+# }
+# },
+# "server" : true,
+# "wait" : false }}}}
+# <- {"return": {}}
+#
+##
+{ 'command': 'chardev-change', 'data': {'id' : 'str',
+ 'backend' : 'ChardevBackend' },
+ 'returns': 'ChardevReturn' }
+
+##
# @chardev-remove:
#
# Remove a character device backend
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 11/41] char: forbid direct chardevice access for hotswap devices
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (9 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 10/41] char: chardevice hotswap Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 12/41] char: avoid chardevice direct access Paolo Bonzini
` (30 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
qemu_chr_fe_get_driver() is unsafe, frontends with hotswap support
should not access CharDriver ptr directly as CharDriver might change.
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1499342940-56739-5-git-send-email-anton.nefedov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
chardev/char-fe.c | 7 +++++++
include/chardev/char-fe.h | 10 ++++++++++
2 files changed, 17 insertions(+)
diff --git a/chardev/char-fe.c b/chardev/char-fe.c
index 7054863..de5ba3c 100644
--- a/chardev/char-fe.c
+++ b/chardev/char-fe.c
@@ -179,9 +179,16 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
Chardev *qemu_chr_fe_get_driver(CharBackend *be)
{
+ /* this is unsafe for the users that support chardev hotswap */
+ assert(be->chr_be_change == NULL);
return be->chr;
}
+bool qemu_chr_fe_backend_connected(CharBackend *be)
+{
+ return !!be->chr;
+}
+
bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp)
{
int tag = 0;
diff --git a/include/chardev/char-fe.h b/include/chardev/char-fe.h
index 9f38060..588abed 100644
--- a/include/chardev/char-fe.h
+++ b/include/chardev/char-fe.h
@@ -46,10 +46,20 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del);
*
* Returns the driver associated with a CharBackend or NULL if no
* associated Chardev.
+ * Note: avoid this function as the driver should never be accessed directly,
+ * especially by the frontends that support chardevice hotswap.
+ * Consider qemu_chr_fe_backend_connected() to check for driver existence
*/
Chardev *qemu_chr_fe_get_driver(CharBackend *be);
/**
+ * @qemu_chr_fe_backend_connected:
+ *
+ * Returns true if there is a chardevice associated with @be.
+ */
+bool qemu_chr_fe_backend_connected(CharBackend *be);
+
+/**
* @qemu_chr_fe_set_handlers:
* @b: a CharBackend
* @fd_can_read: callback to get the amount of data the frontend may
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 12/41] char: avoid chardevice direct access
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (10 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 11/41] char: forbid direct chardevice access for hotswap devices Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 13/41] test-char: destroy chardev-udp after test Paolo Bonzini
` (29 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
frontends should avoid accessing CharDriver struct where possible
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1499342940-56739-6-git-send-email-anton.nefedov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
chardev/char-fe.c | 5 +++++
hw/arm/strongarm.c | 2 +-
hw/char/cadence_uart.c | 2 +-
hw/char/debugcon.c | 2 +-
hw/char/escc.c | 6 +++---
hw/char/exynos4210_uart.c | 2 +-
hw/char/grlib_apbuart.c | 2 +-
hw/char/ipoctal232.c | 2 +-
hw/char/parallel.c | 2 +-
hw/char/sclpconsole-lm.c | 2 +-
hw/char/sclpconsole.c | 2 +-
hw/char/serial.c | 2 +-
hw/char/sh_serial.c | 2 +-
hw/char/spapr_vty.c | 2 +-
hw/char/terminal3270.c | 2 +-
hw/char/virtio-console.c | 5 ++---
hw/char/xen_console.c | 2 +-
hw/ipmi/ipmi_bmc_extern.c | 2 +-
hw/misc/ivshmem.c | 4 ++--
hw/usb/ccid-card-passthru.c | 4 ++--
hw/usb/dev-serial.c | 5 ++---
hw/usb/redirect.c | 5 ++---
include/chardev/char-fe.h | 7 +++++++
net/filter-mirror.c | 2 +-
24 files changed, 41 insertions(+), 32 deletions(-)
diff --git a/chardev/char-fe.c b/chardev/char-fe.c
index de5ba3c..f3af6ae 100644
--- a/chardev/char-fe.c
+++ b/chardev/char-fe.c
@@ -189,6 +189,11 @@ bool qemu_chr_fe_backend_connected(CharBackend *be)
return !!be->chr;
}
+bool qemu_chr_fe_backend_open(CharBackend *be)
+{
+ return be->chr && be->chr->be_open;
+}
+
bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp)
{
int tag = 0;
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index 1fa082c..6a45dcc 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -1106,7 +1106,7 @@ static void strongarm_uart_tx(void *opaque)
if (s->utcr3 & UTCR3_LBM) /* loopback */ {
strongarm_uart_receive(s, &s->tx_fifo[s->tx_start], 1);
- } else if (qemu_chr_fe_get_driver(&s->chr)) {
+ } else if (qemu_chr_fe_backend_connected(&s->chr)) {
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &s->tx_fifo[s->tx_start], 1);
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 3a9335c..6143494 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -279,7 +279,7 @@ static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
int ret;
/* instant drain the fifo when there's no back-end */
- if (!qemu_chr_fe_get_driver(&s->chr)) {
+ if (!qemu_chr_fe_backend_connected(&s->chr)) {
s->tx_count = 0;
return FALSE;
}
diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
index 9b56fb8..95ccec6 100644
--- a/hw/char/debugcon.c
+++ b/hw/char/debugcon.c
@@ -87,7 +87,7 @@ static const MemoryRegionOps debugcon_ops = {
static void debugcon_realize_core(DebugconState *s, Error **errp)
{
- if (!qemu_chr_fe_get_driver(&s->chr)) {
+ if (!qemu_chr_fe_backend_connected(&s->chr)) {
error_setg(errp, "Can't create debugcon device, empty char device");
return;
}
diff --git a/hw/char/escc.c b/hw/char/escc.c
index 3546df3..89ae9eb 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -417,7 +417,7 @@ static void escc_update_parameters(ChannelState *s)
int speed, parity, data_bits, stop_bits;
QEMUSerialSetParams ssp;
- if (!qemu_chr_fe_get_driver(&s->chr) || s->type != ser)
+ if (!qemu_chr_fe_backend_connected(&s->chr) || s->type != ser)
return;
if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
@@ -557,7 +557,7 @@ static void escc_mem_write(void *opaque, hwaddr addr,
trace_escc_mem_writeb_data(CHN_C(s), val);
s->tx = val;
if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
- if (qemu_chr_fe_get_driver(&s->chr)) {
+ if (qemu_chr_fe_backend_connected(&s->chr)) {
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &s->tx, 1);
@@ -1013,7 +1013,7 @@ static void escc_realize(DeviceState *dev, Error **errp)
ESCC_SIZE << s->it_shift);
for (i = 0; i < 2; i++) {
- if (qemu_chr_fe_get_driver(&s->chn[i].chr)) {
+ if (qemu_chr_fe_backend_connected(&s->chn[i].chr)) {
s->chn[i].clock = s->frequency / 2;
qemu_chr_fe_set_handlers(&s->chn[i].chr, serial_can_receive,
serial_receive1, serial_event, NULL,
diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index a84d2c3..3957e78 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -380,7 +380,7 @@ static void exynos4210_uart_write(void *opaque, hwaddr offset,
break;
case UTXH:
- if (qemu_chr_fe_get_driver(&s->chr)) {
+ if (qemu_chr_fe_backend_connected(&s->chr)) {
s->reg[I_(UTRSTAT)] &= ~(UTRSTAT_TRANSMITTER_EMPTY |
UTRSTAT_Tx_BUFFER_EMPTY);
ch = (uint8_t)val;
diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
index 12d0c99..bac11be 100644
--- a/hw/char/grlib_apbuart.c
+++ b/hw/char/grlib_apbuart.c
@@ -201,7 +201,7 @@ static void grlib_apbuart_write(void *opaque, hwaddr addr,
case DATA_OFFSET:
case DATA_OFFSET + 3: /* When only one byte write */
/* Transmit when character device available and transmitter enabled */
- if (qemu_chr_fe_get_driver(&uart->chr) &&
+ if (qemu_chr_fe_backend_connected(&uart->chr) &&
(uart->control & UART_TRANSMIT_ENABLE)) {
c = value & 0xFF;
/* XXX this blocks entire thread. Rewrite to use
diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c
index cc8c8dc..5e09caf 100644
--- a/hw/char/ipoctal232.c
+++ b/hw/char/ipoctal232.c
@@ -542,7 +542,7 @@ static void ipoctal_realize(DeviceState *dev, Error **errp)
ch->ipoctal = s;
/* Redirect IP-Octal channels to host character devices */
- if (qemu_chr_fe_get_driver(&ch->dev)) {
+ if (qemu_chr_fe_backend_connected(&ch->dev)) {
qemu_chr_fe_set_handlers(&ch->dev, hostdev_can_receive,
hostdev_receive, hostdev_event,
NULL, ch, NULL, true);
diff --git a/hw/char/parallel.c b/hw/char/parallel.c
index 75a1a2f..055789f 100644
--- a/hw/char/parallel.c
+++ b/hw/char/parallel.c
@@ -513,7 +513,7 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
int base;
uint8_t dummy;
- if (!qemu_chr_fe_get_driver(&s->chr)) {
+ if (!qemu_chr_fe_backend_connected(&s->chr)) {
error_setg(errp, "Can't create parallel device, empty char device");
return;
}
diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index 741c641..c500bda 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -195,7 +195,7 @@ static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len)
{
SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
- if (!qemu_chr_fe_get_driver(&scon->chr)) {
+ if (!qemu_chr_fe_backend_connected(&scon->chr)) {
/* If there's no backend, we can just say we consumed all data. */
return len;
}
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index a92baa8..d0265df 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -163,7 +163,7 @@ static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf,
{
SCLPConsole *scon = SCLP_CONSOLE(event);
- if (!qemu_chr_fe_get_driver(&scon->chr)) {
+ if (!qemu_chr_fe_backend_connected(&scon->chr)) {
/* If there's no backend, we can just say we consumed all data. */
return len;
}
diff --git a/hw/char/serial.c b/hw/char/serial.c
index ab14ca4..b4fb8f3 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -886,7 +886,7 @@ static void serial_reset(void *opaque)
void serial_realize_core(SerialState *s, Error **errp)
{
- if (!qemu_chr_fe_get_driver(&s->chr)) {
+ if (!qemu_chr_fe_backend_connected(&s->chr)) {
error_setg(errp, "Can't create serial device, empty char device");
return;
}
diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c
index ad043bd..835b537 100644
--- a/hw/char/sh_serial.c
+++ b/hw/char/sh_serial.c
@@ -110,7 +110,7 @@ static void sh_serial_write(void *opaque, hwaddr offs,
}
return;
case 0x0c: /* FTDR / TDR */
- if (qemu_chr_fe_get_driver(&s->chr)) {
+ if (qemu_chr_fe_backend_connected(&s->chr)) {
ch = val;
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
index ddd1b00..0fa416c 100644
--- a/hw/char/spapr_vty.c
+++ b/hw/char/spapr_vty.c
@@ -78,7 +78,7 @@ static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp)
{
VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
- if (!qemu_chr_fe_get_driver(&dev->chardev)) {
+ if (!qemu_chr_fe_backend_connected(&dev->chardev)) {
error_setg(errp, "chardev property not set");
return;
}
diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c
index 5adf95b..28f5991 100644
--- a/hw/char/terminal3270.c
+++ b/hw/char/terminal3270.c
@@ -239,7 +239,7 @@ static int write_payload_3270(EmulatedCcw3270Device *dev, uint8_t cmd,
return 0;
}
}
- if (!qemu_chr_fe_get_driver(&t->chr)) {
+ if (!qemu_chr_fe_backend_connected(&t->chr)) {
/* We just say we consumed all data if there's no backend. */
return count;
}
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index afb4949..4d3967c 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -49,7 +49,7 @@ static ssize_t flush_buf(VirtIOSerialPort *port,
VirtConsole *vcon = VIRTIO_CONSOLE(port);
ssize_t ret;
- if (!qemu_chr_fe_get_driver(&vcon->chr)) {
+ if (!qemu_chr_fe_backend_connected(&vcon->chr)) {
/* If there's no backend, we can just say we consumed all data. */
return len;
}
@@ -168,7 +168,6 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
VirtConsole *vcon = VIRTIO_CONSOLE(dev);
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
- Chardev *chr = qemu_chr_fe_get_driver(&vcon->chr);
if (port->id == 0 && !k->is_console) {
error_setg(errp, "Port number 0 on virtio-serial devices reserved "
@@ -176,7 +175,7 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
return;
}
- if (chr) {
+ if (qemu_chr_fe_backend_connected(&vcon->chr)) {
/*
* For consoles we don't block guest data transfer just
* because nothing is connected - we'll just let it go
diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c
index c4e8c72..3643dfe 100644
--- a/hw/char/xen_console.c
+++ b/hw/char/xen_console.c
@@ -150,7 +150,7 @@ static void xencons_send(struct XenConsole *con)
ssize_t len, size;
size = con->buffer.size - con->buffer.consumed;
- if (qemu_chr_fe_get_driver(&con->chr)) {
+ if (qemu_chr_fe_backend_connected(&con->chr)) {
len = qemu_chr_fe_write(&con->chr,
con->buffer.data + con->buffer.consumed,
size);
diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c
index 182de58..abab3bb 100644
--- a/hw/ipmi/ipmi_bmc_extern.c
+++ b/hw/ipmi/ipmi_bmc_extern.c
@@ -447,7 +447,7 @@ static void ipmi_bmc_extern_realize(DeviceState *dev, Error **errp)
{
IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(dev);
- if (!qemu_chr_fe_get_driver(&ibe->chr)) {
+ if (!qemu_chr_fe_backend_connected(&ibe->chr)) {
error_setg(errp, "IPMI external bmc requires chardev attribute");
return;
}
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index a857e50..7f678d0 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -1128,7 +1128,7 @@ static void ivshmem_doorbell_realize(PCIDevice *dev, Error **errp)
{
IVShmemState *s = IVSHMEM_COMMON(dev);
- if (!qemu_chr_fe_get_driver(&s->server_chr)) {
+ if (!qemu_chr_fe_backend_connected(&s->server_chr)) {
error_setg(errp, "You must specify a 'chardev'");
return;
}
@@ -1257,7 +1257,7 @@ static void ivshmem_realize(PCIDevice *dev, Error **errp)
" or ivshmem-doorbell instead");
}
- if (!!qemu_chr_fe_get_driver(&s->server_chr) + !!s->shmobj != 1) {
+ if (qemu_chr_fe_backend_connected(&s->server_chr) + !!s->shmobj != 1) {
error_setg(errp, "You must specify either 'shm' or 'chardev'");
return;
}
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index e9f58c9..45d96b0 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -322,7 +322,7 @@ static void passthru_apdu_from_guest(
{
PassthruState *card = PASSTHRU_CCID_CARD(base);
- if (!qemu_chr_fe_get_driver(&card->cs)) {
+ if (!qemu_chr_fe_backend_connected(&card->cs)) {
printf("ccid-passthru: no chardev, discarding apdu length %d\n", len);
return;
}
@@ -343,7 +343,7 @@ static int passthru_initfn(CCIDCardState *base)
card->vscard_in_pos = 0;
card->vscard_in_hdr = 0;
- if (qemu_chr_fe_get_driver(&card->cs)) {
+ if (qemu_chr_fe_backend_connected(&card->cs)) {
DPRINTF(card, D_INFO, "initing chardev\n");
qemu_chr_fe_set_handlers(&card->cs,
ccid_card_vscard_can_read,
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index dc145a6..94b5c34 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -484,13 +484,12 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
{
USBSerialState *s = USB_SERIAL_DEV(dev);
Error *local_err = NULL;
- Chardev *chr = qemu_chr_fe_get_driver(&s->cs);
usb_desc_create_serial(dev);
usb_desc_init(dev);
dev->auto_attach = 0;
- if (!chr) {
+ if (!qemu_chr_fe_backend_connected(&s->cs)) {
error_setg(errp, "Property chardev is required");
return;
}
@@ -505,7 +504,7 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
usb_serial_event, NULL, s, NULL, true);
usb_serial_handle_reset(dev);
- if (chr->be_open && !dev->attached) {
+ if (qemu_chr_fe_backend_open(&s->cs) && !dev->attached) {
usb_device_attach(dev, &error_abort);
}
}
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 115efb9..c597145 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -273,10 +273,9 @@ static gboolean usbredir_write_unblocked(GIOChannel *chan, GIOCondition cond,
static int usbredir_write(void *priv, uint8_t *data, int count)
{
USBRedirDevice *dev = priv;
- Chardev *chr = qemu_chr_fe_get_driver(&dev->cs);
int r;
- if (!chr->be_open) {
+ if (!qemu_chr_fe_backend_open(&dev->cs)) {
return 0;
}
@@ -1366,7 +1365,7 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
USBRedirDevice *dev = USB_REDIRECT(udev);
int i;
- if (!qemu_chr_fe_get_driver(&dev->cs)) {
+ if (!qemu_chr_fe_backend_connected(&dev->cs)) {
error_setg(errp, QERR_MISSING_PARAMETER, "chardev");
return;
}
diff --git a/include/chardev/char-fe.h b/include/chardev/char-fe.h
index 588abed..71cd069 100644
--- a/include/chardev/char-fe.h
+++ b/include/chardev/char-fe.h
@@ -60,6 +60,13 @@ Chardev *qemu_chr_fe_get_driver(CharBackend *be);
bool qemu_chr_fe_backend_connected(CharBackend *be);
/**
+ * @qemu_chr_fe_backend_open:
+ *
+ * Returns true if chardevice associated with @be is open.
+ */
+bool qemu_chr_fe_backend_open(CharBackend *be);
+
+/**
* @qemu_chr_fe_set_handlers:
* @b: a CharBackend
* @fd_can_read: callback to get the amount of data the frontend may
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index 62a8265..6043549 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -163,7 +163,7 @@ static ssize_t filter_redirector_receive_iov(NetFilterState *nf,
MirrorState *s = FILTER_REDIRECTOR(nf);
int ret;
- if (qemu_chr_fe_get_driver(&s->chr_out)) {
+ if (qemu_chr_fe_backend_connected(&s->chr_out)) {
ret = filter_send(&s->chr_out, iov, iovcnt);
if (ret) {
error_report("filter redirector send failed(%s)", strerror(-ret));
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 13/41] test-char: destroy chardev-udp after test
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (11 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 12/41] char: avoid chardevice direct access Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 14/41] test-char: split char_udp_test Paolo Bonzini
` (28 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
this is only not a problem if the test is last in a suite,
otherwise it makes the following main_loop() calls to fail
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1499342940-56739-7-git-send-email-anton.nefedov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
tests/test-char.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test-char.c b/tests/test-char.c
index 38aaa27..536536e 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -450,6 +450,7 @@ static void char_udp_test(void)
close(sock);
g_free(tmp);
+ qemu_chr_fe_deinit(&be, true);
}
#ifdef HAVE_CHARDEV_SERIAL
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 14/41] test-char: split char_udp_test
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (12 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 13/41] test-char: destroy chardev-udp after test Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 15/41] test-char: split char_file_test Paolo Bonzini
` (27 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
makes it possible to test the existing chardev-udp
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1499342940-56739-8-git-send-email-anton.nefedov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
tests/test-char.c | 56 +++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 40 insertions(+), 16 deletions(-)
diff --git a/tests/test-char.c b/tests/test-char.c
index 536536e..e0bde5e 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -407,16 +407,11 @@ static void char_pipe_test(void)
}
#endif
-static void char_udp_test(void)
+static int make_udp_socket(int *port)
{
- struct sockaddr_in addr = { 0, }, other;
- SocketIdleData d = { 0, };
- Chardev *chr;
- CharBackend be;
+ struct sockaddr_in addr = { 0, };
socklen_t alen = sizeof(addr);
int ret, sock = qemu_socket(PF_INET, SOCK_DGRAM, 0);
- char buf[10];
- char *tmp;
g_assert_cmpint(sock, >, 0);
addr.sin_family = AF_INET ;
@@ -427,19 +422,41 @@ static void char_udp_test(void)
ret = getsockname(sock, (struct sockaddr *)&addr, &alen);
g_assert_cmpint(ret, ==, 0);
- tmp = g_strdup_printf("udp:127.0.0.1:%d",
- ntohs(addr.sin_port));
- chr = qemu_chr_new("client", tmp);
- g_assert_nonnull(chr);
+ *port = ntohs(addr.sin_port);
+ return sock;
+}
+
+static void char_udp_test_internal(Chardev *reuse_chr, int sock)
+{
+ struct sockaddr_in other;
+ SocketIdleData d = { 0, };
+ Chardev *chr;
+ CharBackend *be;
+ socklen_t alen = sizeof(other);
+ int ret;
+ char buf[10];
+ char *tmp = NULL;
+
+ if (reuse_chr) {
+ chr = reuse_chr;
+ be = chr->be;
+ } else {
+ int port;
+ sock = make_udp_socket(&port);
+ tmp = g_strdup_printf("udp:127.0.0.1:%d", port);
+ chr = qemu_chr_new("client", tmp);
+ g_assert_nonnull(chr);
+
+ be = g_alloca(sizeof(CharBackend));
+ qemu_chr_fe_init(be, chr, &error_abort);
+ }
d.chr = chr;
- qemu_chr_fe_init(&be, chr, &error_abort);
- qemu_chr_fe_set_handlers(&be, socket_can_read_hello, socket_read_hello,
+ qemu_chr_fe_set_handlers(be, socket_can_read_hello, socket_read_hello,
NULL, NULL, &d, NULL, true);
ret = qemu_chr_write_all(chr, (uint8_t *)"hello", 5);
g_assert_cmpint(ret, ==, 5);
- alen = sizeof(addr);
ret = recvfrom(sock, buf, sizeof(buf), 0,
(struct sockaddr *)&other, &alen);
g_assert_cmpint(ret, ==, 5);
@@ -448,9 +465,16 @@ static void char_udp_test(void)
main_loop();
- close(sock);
+ if (!reuse_chr) {
+ close(sock);
+ qemu_chr_fe_deinit(be, true);
+ }
g_free(tmp);
- qemu_chr_fe_deinit(&be, true);
+}
+
+static void char_udp_test(void)
+{
+ char_udp_test_internal(NULL, 0);
}
#ifdef HAVE_CHARDEV_SERIAL
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 15/41] test-char: split char_file_test
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (13 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 14/41] test-char: split char_udp_test Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 16/41] test-char: add hotswap test Paolo Bonzini
` (26 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
makes it possible to test the existing chardev-file
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1499342940-56739-9-git-send-email-anton.nefedov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
tests/test-char.c | 137 +++++++++++++++++++++++++++++++++---------------------
1 file changed, 84 insertions(+), 53 deletions(-)
diff --git a/tests/test-char.c b/tests/test-char.c
index e0bde5e..c654eea 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -503,82 +503,110 @@ static void char_serial_test(void)
}
#endif
-static void char_file_test(void)
+#ifndef _WIN32
+static void char_file_fifo_test(void)
{
+ Chardev *chr;
+ CharBackend be;
char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
+ char *fifo = g_build_filename(tmp_path, "fifo", NULL);
char *out = g_build_filename(tmp_path, "out", NULL);
- char *contents = NULL;
- ChardevFile file = { .out = out };
+ ChardevFile file = { .in = fifo,
+ .has_in = true,
+ .out = out };
ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
.u.file.data = &file };
+ FeHandler fe = { 0, };
+ int fd, ret;
+
+ if (mkfifo(fifo, 0600) < 0) {
+ abort();
+ }
+
+ fd = open(fifo, O_RDWR);
+ ret = write(fd, "fifo-in", 8);
+ g_assert_cmpint(ret, ==, 8);
+
+ chr = qemu_chardev_new("label-file", TYPE_CHARDEV_FILE, &backend,
+ &error_abort);
+
+ qemu_chr_fe_init(&be, chr, &error_abort);
+ qemu_chr_fe_set_handlers(&be,
+ fe_can_read,
+ fe_read,
+ fe_event,
+ NULL,
+ &fe, NULL, true);
+
+ g_assert_cmpint(fe.last_event, !=, CHR_EVENT_BREAK);
+ qmp_chardev_send_break("label-foo", NULL);
+ g_assert_cmpint(fe.last_event, !=, CHR_EVENT_BREAK);
+ qmp_chardev_send_break("label-file", NULL);
+ g_assert_cmpint(fe.last_event, ==, CHR_EVENT_BREAK);
+
+ main_loop();
+
+ close(fd);
+
+ g_assert_cmpint(fe.read_count, ==, 8);
+ g_assert_cmpstr(fe.read_buf, ==, "fifo-in");
+
+ qemu_chr_fe_deinit(&be, true);
+
+ g_unlink(fifo);
+ g_free(fifo);
+ g_unlink(out);
+ g_free(out);
+ g_rmdir(tmp_path);
+ g_free(tmp_path);
+}
+#endif
+
+static void char_file_test_internal(Chardev *ext_chr, const char *filepath)
+{
+ char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
+ char *out;
Chardev *chr;
+ char *contents = NULL;
+ ChardevFile file = {};
+ ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
+ .u.file.data = &file };
gsize length;
int ret;
- chr = qemu_chardev_new(NULL, TYPE_CHARDEV_FILE, &backend,
- &error_abort);
+ if (ext_chr) {
+ chr = ext_chr;
+ out = g_strdup(filepath);
+ file.out = out;
+ } else {
+ out = g_build_filename(tmp_path, "out", NULL);
+ file.out = out;
+ chr = qemu_chardev_new(NULL, TYPE_CHARDEV_FILE, &backend,
+ &error_abort);
+ }
ret = qemu_chr_write_all(chr, (uint8_t *)"hello!", 6);
g_assert_cmpint(ret, ==, 6);
- object_unref(OBJECT(chr));
ret = g_file_get_contents(out, &contents, &length, NULL);
g_assert(ret == TRUE);
g_assert_cmpint(length, ==, 6);
g_assert(strncmp(contents, "hello!", 6) == 0);
- g_free(contents);
-
-#ifndef _WIN32
- {
- CharBackend be;
- FeHandler fe = { 0, };
- char *fifo = g_build_filename(tmp_path, "fifo", NULL);
- int fd;
-
- if (mkfifo(fifo, 0600) < 0) {
- abort();
- }
-
- fd = open(fifo, O_RDWR);
- ret = write(fd, "fifo-in", 8);
- g_assert_cmpint(ret, ==, 8);
-
- file.in = fifo;
- file.has_in = true;
- chr = qemu_chardev_new("label-file", TYPE_CHARDEV_FILE, &backend,
- &error_abort);
- qemu_chr_fe_init(&be, chr, &error_abort);
- qemu_chr_fe_set_handlers(&be,
- fe_can_read,
- fe_read,
- fe_event,
- NULL,
- &fe, NULL, true);
-
- g_assert_cmpint(fe.last_event, !=, CHR_EVENT_BREAK);
- qmp_chardev_send_break("label-foo", NULL);
- g_assert_cmpint(fe.last_event, !=, CHR_EVENT_BREAK);
- qmp_chardev_send_break("label-file", NULL);
- g_assert_cmpint(fe.last_event, ==, CHR_EVENT_BREAK);
-
- main_loop();
-
- close(fd);
-
- g_assert_cmpint(fe.read_count, ==, 8);
- g_assert_cmpstr(fe.read_buf, ==, "fifo-in");
- qemu_chr_fe_deinit(&be, true);
- g_unlink(fifo);
- g_free(fifo);
+ if (!ext_chr) {
+ object_unref(OBJECT(chr));
+ g_unlink(out);
}
-#endif
-
- g_unlink(out);
+ g_free(contents);
g_rmdir(tmp_path);
g_free(tmp_path);
g_free(out);
}
+static void char_file_test(void)
+{
+ char_file_test_internal(NULL, NULL);
+}
+
static void char_null_test(void)
{
Error *err = NULL;
@@ -656,6 +684,9 @@ int main(int argc, char **argv)
g_test_add_func("/char/pipe", char_pipe_test);
#endif
g_test_add_func("/char/file", char_file_test);
+#ifndef _WIN32
+ g_test_add_func("/char/file-fifo", char_file_fifo_test);
+#endif
g_test_add_func("/char/socket", char_socket_test);
g_test_add_func("/char/udp", char_udp_test);
#ifdef HAVE_CHARDEV_SERIAL
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 16/41] test-char: add hotswap test
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (14 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 15/41] test-char: split char_file_test Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 17/41] hmp: add hmp analogue for qmp-chardev-change Paolo Bonzini
` (25 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1499342940-56739-10-git-send-email-anton.nefedov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
tests/test-char.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
diff --git a/tests/test-char.c b/tests/test-char.c
index c654eea..7ac25ff 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -658,6 +658,76 @@ static void char_invalid_test(void)
g_assert_null(chr);
}
+static int chardev_change(void *opaque)
+{
+ return 0;
+}
+
+static int chardev_change_denied(void *opaque)
+{
+ return -1;
+}
+
+static void char_hotswap_test(void)
+{
+ char *chr_args;
+ Chardev *chr;
+ CharBackend be;
+
+ gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
+ char *filename = g_build_filename(tmp_path, "file", NULL);
+ ChardevFile file = { .out = filename };
+ ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
+ .u.file.data = &file };
+ ChardevReturn *ret;
+
+ int port;
+ int sock = make_udp_socket(&port);
+ g_assert_cmpint(sock, >, 0);
+
+ chr_args = g_strdup_printf("udp:127.0.0.1:%d", port);
+
+ chr = qemu_chr_new("chardev", chr_args);
+ qemu_chr_fe_init(&be, chr, &error_abort);
+
+ /* check that chardev operates correctly */
+ char_udp_test_internal(chr, sock);
+
+ /* set the handler that denies the hotswap */
+ qemu_chr_fe_set_handlers(&be, NULL, NULL,
+ NULL, chardev_change_denied, NULL, NULL, true);
+
+ /* now, change is denied and has to keep the old backend operating */
+ ret = qmp_chardev_change("chardev", &backend, NULL);
+ g_assert(!ret);
+ g_assert(be.chr == chr);
+
+ char_udp_test_internal(chr, sock);
+
+ /* now allow the change */
+ qemu_chr_fe_set_handlers(&be, NULL, NULL,
+ NULL, chardev_change, NULL, NULL, true);
+
+ /* has to succeed now */
+ ret = qmp_chardev_change("chardev", &backend, &error_abort);
+ g_assert(be.chr != chr);
+
+ close(sock);
+ chr = be.chr;
+
+ /* run the file chardev test */
+ char_file_test_internal(chr, filename);
+
+ object_unparent(OBJECT(chr));
+
+ qapi_free_ChardevReturn(ret);
+ g_unlink(filename);
+ g_free(filename);
+ g_rmdir(tmp_path);
+ g_free(tmp_path);
+ g_free(chr_args);
+}
+
int main(int argc, char **argv)
{
qemu_init_main_loop(&error_abort);
@@ -692,6 +762,7 @@ int main(int argc, char **argv)
#ifdef HAVE_CHARDEV_SERIAL
g_test_add_func("/char/serial", char_serial_test);
#endif
+ g_test_add_func("/char/hotswap", char_hotswap_test);
return g_test_run();
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 17/41] hmp: add hmp analogue for qmp-chardev-change
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (15 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 16/41] test-char: add hotswap test Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 18/41] virtio-console: chardev hotswap support Paolo Bonzini
` (24 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-Id: <1499342940-56739-11-git-send-email-anton.nefedov@virtuozzo.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
chardev/char.c | 2 +-
hmp-commands.hx | 18 +++++++++++++++++-
hmp.c | 34 ++++++++++++++++++++++++++++++++++
hmp.h | 1 +
include/chardev/char.h | 10 ++++++++++
tests/test-hmp.c | 1 +
6 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/chardev/char.c b/chardev/char.c
index d6b9d89..c34b44a 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -567,7 +567,7 @@ static const char *chardev_alias_translate(const char *name)
return name;
}
-static ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts, Error **errp)
+ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts, Error **errp)
{
Error *local_err = NULL;
const ChardevClass *cc;
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 275ccdf..c4c96db 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1724,7 +1724,23 @@ ETEXI
STEXI
@item chardev-add args
@findex chardev-add
-chardev_add accepts the same parameters as the -chardev command line switch.
+chardev-add accepts the same parameters as the -chardev command line switch.
+
+ETEXI
+
+ {
+ .name = "chardev-change",
+ .args_type = "id:s,args:s",
+ .params = "id args",
+ .help = "change chardev",
+ .cmd = hmp_chardev_change,
+ },
+
+STEXI
+@item chardev-change args
+@findex chardev-change
+chardev-change accepts existing chardev @var{id} and then the same arguments
+as the -chardev command line switch (except for "id").
ETEXI
diff --git a/hmp.c b/hmp.c
index dee4028..1b443e1 100644
--- a/hmp.c
+++ b/hmp.c
@@ -2228,6 +2228,40 @@ void hmp_chardev_add(Monitor *mon, const QDict *qdict)
hmp_handle_error(mon, &err);
}
+void hmp_chardev_change(Monitor *mon, const QDict *qdict)
+{
+ const char *args = qdict_get_str(qdict, "args");
+ const char *id;
+ Error *err = NULL;
+ ChardevBackend *backend = NULL;
+ ChardevReturn *ret = NULL;
+ QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), args,
+ true);
+ if (!opts) {
+ error_setg(&err, "Parsing chardev args failed");
+ goto end;
+ }
+
+ id = qdict_get_str(qdict, "id");
+ if (qemu_opts_id(opts)) {
+ error_setg(&err, "Unexpected 'id' parameter");
+ goto end;
+ }
+
+ backend = qemu_chr_parse_opts(opts, &err);
+ if (!backend) {
+ goto end;
+ }
+
+ ret = qmp_chardev_change(id, backend, &err);
+
+end:
+ qapi_free_ChardevReturn(ret);
+ qapi_free_ChardevBackend(backend);
+ qemu_opts_del(opts);
+ hmp_handle_error(mon, &err);
+}
+
void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
{
Error *local_err = NULL;
diff --git a/hmp.h b/hmp.h
index 214b261..1ff4552 100644
--- a/hmp.h
+++ b/hmp.h
@@ -102,6 +102,7 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict);
void hmp_nbd_server_add(Monitor *mon, const QDict *qdict);
void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
void hmp_chardev_add(Monitor *mon, const QDict *qdict);
+void hmp_chardev_change(Monitor *mon, const QDict *qdict);
void hmp_chardev_remove(Monitor *mon, const QDict *qdict);
void hmp_chardev_send_break(Monitor *mon, const QDict *qdict);
void hmp_qemu_io(Monitor *mon, const QDict *qdict);
diff --git a/include/chardev/char.h b/include/chardev/char.h
index 22fd734..1604ea9 100644
--- a/include/chardev/char.h
+++ b/include/chardev/char.h
@@ -81,6 +81,16 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend);
/**
+ * @qemu_chr_parse_opts:
+ *
+ * Parse the options to the ChardevBackend struct.
+ *
+ * Returns: a new backend or NULL on error
+ */
+ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts,
+ Error **errp);
+
+/**
* @qemu_chr_new:
*
* Create a new character backend from a URI.
diff --git a/tests/test-hmp.c b/tests/test-hmp.c
index 6dfa0c3..d77b3c8 100644
--- a/tests/test-hmp.c
+++ b/tests/test-hmp.c
@@ -23,6 +23,7 @@ static const char *hmp_cmds[] = {
"boot_set ndc",
"chardev-add null,id=testchardev1",
"chardev-send-break testchardev2",
+ "chardev-change testchardev1 ringbuf",
"chardev-remove testchardev1",
"commit all",
"cpu-add 1",
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 18/41] virtio-console: chardev hotswap support
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (16 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 17/41] hmp: add hmp analogue for qmp-chardev-change Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 19/41] serial: move TIOCM update to a separate function Paolo Bonzini
` (23 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
In case of a backend change, the handler functions and the watch have
to be reset.
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <1499342940-56739-12-git-send-email-anton.nefedov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/char/virtio-console.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index 4d3967c..198b2a8 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -163,6 +163,30 @@ static void chr_event(void *opaque, int event)
}
}
+static int chr_be_change(void *opaque)
+{
+ VirtConsole *vcon = opaque;
+ VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon);
+ VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
+
+ if (k->is_console) {
+ qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
+ NULL, chr_be_change, vcon, NULL, true);
+ } else {
+ qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
+ chr_event, chr_be_change, vcon, NULL, false);
+ }
+
+ if (vcon->watch) {
+ g_source_remove(vcon->watch);
+ vcon->watch = qemu_chr_fe_add_watch(&vcon->chr,
+ G_IO_OUT | G_IO_HUP,
+ chr_write_unblocked, vcon);
+ }
+
+ return 0;
+}
+
static void virtconsole_realize(DeviceState *dev, Error **errp)
{
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
@@ -187,11 +211,13 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
*/
if (k->is_console) {
qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
- NULL, NULL, vcon, NULL, true);
+ NULL, chr_be_change,
+ vcon, NULL, true);
virtio_serial_open(port);
} else {
qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
- chr_event, NULL, vcon, NULL, false);
+ chr_event, chr_be_change,
+ vcon, NULL, false);
}
}
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 19/41] serial: move TIOCM update to a separate function
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (17 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 18/41] virtio-console: chardev hotswap support Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 20/41] serial: chardev hotswap support Paolo Bonzini
` (22 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
will be used by the following patch
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1499342940-56739-13-git-send-email-anton.nefedov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/char/serial.c | 31 +++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index b4fb8f3..09157f9 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -312,6 +312,24 @@ static void serial_write_fcr(SerialState *s, uint8_t val)
}
}
+static void serial_update_tiocm(SerialState *s)
+{
+ int flags;
+
+ qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
+
+ flags &= ~(CHR_TIOCM_RTS | CHR_TIOCM_DTR);
+
+ if (s->mcr & UART_MCR_RTS) {
+ flags |= CHR_TIOCM_RTS;
+ }
+ if (s->mcr & UART_MCR_DTR) {
+ flags |= CHR_TIOCM_DTR;
+ }
+
+ qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
+}
+
static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
@@ -426,24 +444,13 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
break;
case 4:
{
- int flags;
int old_mcr = s->mcr;
s->mcr = val & 0x1f;
if (val & UART_MCR_LOOP)
break;
if (s->poll_msl >= 0 && old_mcr != s->mcr) {
-
- qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
-
- flags &= ~(CHR_TIOCM_RTS | CHR_TIOCM_DTR);
-
- if (val & UART_MCR_RTS)
- flags |= CHR_TIOCM_RTS;
- if (val & UART_MCR_DTR)
- flags |= CHR_TIOCM_DTR;
-
- qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
+ serial_update_tiocm(s);
/* Update the modem status after a one-character-send wait-time, since there may be a response
from the device/computer at the other end of the serial line */
timer_mod(s->modem_status_poll, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 20/41] serial: chardev hotswap support
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (18 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 19/41] serial: move TIOCM update to a separate function Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 21/41] exec: use qemu_ram_ptr_length to access guest ram Paolo Bonzini
` (21 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anton Nefedov
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
This allows to change the port's backend runtime, e.g. change it from
file to a socket making it possible to establish a debug session with
WinDbg
> qemu-system [..] -chardev file,id=charchannel2,path=/tmp/charchannel2 \
-device isa-serial,chardev=charchannel2,id=channel2
QEMU 2.9.50 monitor - type 'help' for more information
(qemu) chardev-change charchannel2 \
socket,host=127.0.0.1,port=4242,server,nowait
For a backend change, a number of ioctls has to be replayed to sync
the current setup of a frontend to a backend tty. This is hopefully
enough so we don't have to track, store and replay the whole original
control byte sequence.
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <1499342940-56739-14-git-send-email-anton.nefedov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/char/serial.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 09157f9..9aec6c6 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -891,6 +891,34 @@ static void serial_reset(void *opaque)
s->msr &= ~UART_MSR_ANY_DELTA;
}
+static int serial_be_change(void *opaque)
+{
+ SerialState *s = opaque;
+
+ qemu_chr_fe_set_handlers(&s->chr, serial_can_receive1, serial_receive1,
+ serial_event, serial_be_change, s, NULL, true);
+
+ serial_update_parameters(s);
+
+ qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
+ &s->last_break_enable);
+
+ s->poll_msl = (s->ier & UART_IER_MSI) ? 1 : 0;
+ serial_update_msl(s);
+
+ if (s->poll_msl >= 0 && !(s->mcr & UART_MCR_LOOP)) {
+ serial_update_tiocm(s);
+ }
+
+ if (s->watch_tag > 0) {
+ g_source_remove(s->watch_tag);
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
+ serial_watch_cb, s);
+ }
+
+ return 0;
+}
+
void serial_realize_core(SerialState *s, Error **errp)
{
if (!qemu_chr_fe_backend_connected(&s->chr)) {
@@ -904,7 +932,7 @@ void serial_realize_core(SerialState *s, Error **errp)
qemu_register_reset(serial_reset, s);
qemu_chr_fe_set_handlers(&s->chr, serial_can_receive1, serial_receive1,
- serial_event, NULL, s, NULL, true);
+ serial_event, serial_be_change, s, NULL, true);
fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
serial_reset(s);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 21/41] exec: use qemu_ram_ptr_length to access guest ram
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (19 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 20/41] serial: chardev hotswap support Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 22/41] Revert "exec.c: Fix breakpoint invalidation race" Paolo Bonzini
` (20 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Prasad J Pandit
From: Prasad J Pandit <pjp@fedoraproject.org>
When accessing guest's ram block during DMA operation, use
'qemu_ram_ptr_length' to get ram block pointer. It ensures
that DMA operation of given length is possible; And avoids
any OOB memory access situations.
Reported-by: Alex <broscutamaker@gmail.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <20170712123840.29328-1-ppandit@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
exec.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/exec.c b/exec.c
index a083ff8..ad103ce 100644
--- a/exec.c
+++ b/exec.c
@@ -2929,7 +2929,7 @@ static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr,
}
} else {
/* RAM case */
- ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
+ ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l);
memcpy(ptr, buf, l);
invalidate_and_set_dirty(mr, addr1, l);
}
@@ -3020,7 +3020,7 @@ MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr,
}
} else {
/* RAM case */
- ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
+ ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l);
memcpy(buf, ptr, l);
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 22/41] Revert "exec.c: Fix breakpoint invalidation race"
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (20 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 21/41] exec: use qemu_ram_ptr_length to access guest ram Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 23/41] mttcg/i386: Patch instruction using async_safe_* framework Paolo Bonzini
` (19 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Pranith Kumar, Peter Maydell, Alex Bennée
From: Pranith Kumar <bobby.prani@gmail.com>
Now that we have proper locking after MTTCG patches have landed, we
can revert the commit. This reverts commit
a9353fe897ca2687e5b3385ed39e3db3927a90e0.
CC: Peter Maydell <peter.maydell@linaro.org>
CC: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
Message-Id: <20170712215143.19594-1-bobby.prani@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
exec.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/exec.c b/exec.c
index ad103ce..2e8bc43 100644
--- a/exec.c
+++ b/exec.c
@@ -775,15 +775,28 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
#endif
}
+#if defined(CONFIG_USER_ONLY)
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
{
- /* Flush the whole TB as this will not have race conditions
- * even if we don't have proper locking yet.
- * Ideally we would just invalidate the TBs for the
- * specified PC.
- */
- tb_flush(cpu);
+ mmap_lock();
+ tb_lock();
+ tb_invalidate_phys_page_range(pc, pc + 1, 0);
+ tb_unlock();
+ mmap_unlock();
}
+#else
+static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
+{
+ MemTxAttrs attrs;
+ hwaddr phys = cpu_get_phys_page_attrs_debug(cpu, pc, &attrs);
+ int asidx = cpu_asidx_from_attrs(cpu, attrs);
+ if (phys != -1) {
+ /* Locks grabbed by tb_invalidate_phys_addr */
+ tb_invalidate_phys_addr(cpu->cpu_ases[asidx].as,
+ phys | (pc & ~TARGET_PAGE_MASK));
+ }
+}
+#endif
#if defined(CONFIG_USER_ONLY)
void cpu_watchpoint_remove_all(CPUState *cpu, int mask)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 23/41] mttcg/i386: Patch instruction using async_safe_* framework
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (21 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 22/41] Revert "exec.c: Fix breakpoint invalidation race" Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 15:16 ` Alex Bennée
2017-07-13 14:24 ` [Qemu-devel] [PULL 24/41] gdbstub: modernise DEBUG_GDB Paolo Bonzini
` (18 subsequent siblings)
41 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Pranith Kumar, Peter Maydell
From: Pranith Kumar <bobby.prani@gmail.com>
In mttcg, calling pause_all_vcpus() during execution from the
generated TBs causes a deadlock if some vCPU is waiting for exclusive
execution in start_exclusive(). Fix this by using the aync_safe_*
framework instead of pausing vcpus for patching instructions.
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
Message-Id: <20170712215143.19594-2-bobby.prani@gmail.com>
[Get rid completely of the TCG-specific code. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/i386/kvmvapic.c | 85 +++++++++++++++++++++++++-----------------------------
1 file changed, 39 insertions(+), 46 deletions(-)
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index 0d9ef77..fc962c5 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -383,8 +383,7 @@ static void patch_byte(X86CPU *cpu, target_ulong addr, uint8_t byte)
cpu_memory_rw_debug(CPU(cpu), addr, &byte, 1, 1);
}
-static void patch_call(VAPICROMState *s, X86CPU *cpu, target_ulong ip,
- uint32_t target)
+static void patch_call(X86CPU *cpu, target_ulong ip, uint32_t target)
{
uint32_t offset;
@@ -393,77 +392,71 @@ static void patch_call(VAPICROMState *s, X86CPU *cpu, target_ulong ip,
cpu_memory_rw_debug(CPU(cpu), ip + 1, (void *)&offset, sizeof(offset), 1);
}
-static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
+typedef struct PatchInfo {
+ VAPICHandlers *handler;
+ target_ulong ip;
+} PatchInfo;
+
+static void do_patch_instruction(CPUState *cs, run_on_cpu_data data)
{
- CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
- VAPICHandlers *handlers;
+ X86CPU *x86_cpu = X86_CPU(cs);
+ PatchInfo *info = (PatchInfo *) data.host_ptr;
+ VAPICHandlers *handlers = info->handler;
+ target_ulong ip = info->ip;
uint8_t opcode[2];
uint32_t imm32 = 0;
- target_ulong current_pc = 0;
- target_ulong current_cs_base = 0;
- uint32_t current_flags = 0;
-
- if (smp_cpus == 1) {
- handlers = &s->rom_state.up;
- } else {
- handlers = &s->rom_state.mp;
- }
-
- if (tcg_enabled()) {
- cpu_restore_state(cs, cs->mem_io_pc);
- cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base,
- ¤t_flags);
- /* Account this instruction, because we will exit the tb.
- This is the first instruction in the block. Therefore
- there is no need in restoring CPU state. */
- if (use_icount) {
- --cs->icount_decr.u16.low;
- }
- }
-
- pause_all_vcpus();
cpu_memory_rw_debug(cs, ip, opcode, sizeof(opcode), 0);
switch (opcode[0]) {
case 0x89: /* mov r32 to r/m32 */
- patch_byte(cpu, ip, 0x50 + modrm_reg(opcode[1])); /* push reg */
- patch_call(s, cpu, ip + 1, handlers->set_tpr);
+ patch_byte(x86_cpu, ip, 0x50 + modrm_reg(opcode[1])); /* push reg */
+ patch_call(x86_cpu, ip + 1, handlers->set_tpr);
break;
case 0x8b: /* mov r/m32 to r32 */
- patch_byte(cpu, ip, 0x90);
- patch_call(s, cpu, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
+ patch_byte(x86_cpu, ip, 0x90);
+ patch_call(x86_cpu, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
break;
case 0xa1: /* mov abs to eax */
- patch_call(s, cpu, ip, handlers->get_tpr[0]);
+ patch_call(x86_cpu, ip, handlers->get_tpr[0]);
break;
case 0xa3: /* mov eax to abs */
- patch_call(s, cpu, ip, handlers->set_tpr_eax);
+ patch_call(x86_cpu, ip, handlers->set_tpr_eax);
break;
case 0xc7: /* mov imm32, r/m32 (c7/0) */
- patch_byte(cpu, ip, 0x68); /* push imm32 */
+ patch_byte(x86_cpu, ip, 0x68); /* push imm32 */
cpu_memory_rw_debug(cs, ip + 6, (void *)&imm32, sizeof(imm32), 0);
cpu_memory_rw_debug(cs, ip + 1, (void *)&imm32, sizeof(imm32), 1);
- patch_call(s, cpu, ip + 5, handlers->set_tpr);
+ patch_call(x86_cpu, ip + 5, handlers->set_tpr);
break;
case 0xff: /* push r/m32 */
- patch_byte(cpu, ip, 0x50); /* push eax */
- patch_call(s, cpu, ip + 1, handlers->get_tpr_stack);
+ patch_byte(x86_cpu, ip, 0x50); /* push eax */
+ patch_call(x86_cpu, ip + 1, handlers->get_tpr_stack);
break;
default:
abort();
}
- resume_all_vcpus();
+ g_free(info);
+}
+
+static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
+{
+ CPUState *cs = CPU(cpu);
+ VAPICHandlers *handlers;
+ PatchInfo *info;
- if (tcg_enabled()) {
- /* Both tb_lock and iothread_mutex will be reset when
- * longjmps back into the cpu_exec loop. */
- tb_lock();
- tb_gen_code(cs, current_pc, current_cs_base, current_flags, 1);
- cpu_loop_exit_noexc(cs);
+ if (smp_cpus == 1) {
+ handlers = &s->rom_state.up;
+ } else {
+ handlers = &s->rom_state.mp;
}
+
+ info = g_new(PatchInfo, 1);
+ info->handler = handlers;
+ info->ip = ip;
+
+ async_safe_run_on_cpu(cs, do_patch_instruction, RUN_ON_CPU_HOST_PTR(info));
}
void vapic_report_tpr_access(DeviceState *dev, CPUState *cs, target_ulong ip,
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 24/41] gdbstub: modernise DEBUG_GDB
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (22 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 23/41] mttcg/i386: Patch instruction using async_safe_* framework Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 25/41] gdbstub: rename cpu_index -> cpu_gdb_index Paolo Bonzini
` (17 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée
From: Alex Bennée <alex.bennee@linaro.org>
Convert the a gdb_debug helper which compiles away to nothing when not
used but still ensures the format strings are checked. There is some
minor code motion for the incorrect checksum message to report it
before we attempt to send the reply.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Message-Id: <20170712105216.747-2-alex.bennee@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
gdbstub.c | 77 +++++++++++++++++++++++++++------------------------------------
1 file changed, 33 insertions(+), 44 deletions(-)
diff --git a/gdbstub.c b/gdbstub.c
index e561244..3965980 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -272,7 +272,20 @@ static int gdb_signal_to_target (int sig)
return -1;
}
-//#define DEBUG_GDB
+/* #define DEBUG_GDB */
+
+#ifdef DEBUG_GDB
+# define DEBUG_GDB_GATE 1
+#else
+# define DEBUG_GDB_GATE 0
+#endif
+
+#define gdb_debug(fmt, ...) do { \
+ if (DEBUG_GDB_GATE) { \
+ fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); \
+ } \
+} while (0)
+
typedef struct GDBRegisterState {
int base_reg;
@@ -548,9 +561,7 @@ static int put_packet_binary(GDBState *s, const char *buf, int len)
/* return -1 if error, 0 if OK */
static int put_packet(GDBState *s, const char *buf)
{
-#ifdef DEBUG_GDB
- printf("reply='%s'\n", buf);
-#endif
+ gdb_debug("reply='%s'\n", buf);
return put_packet_binary(s, buf, strlen(buf));
}
@@ -956,9 +967,9 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
uint8_t *registers;
target_ulong addr, len;
-#ifdef DEBUG_GDB
- printf("command='%s'\n", line_buf);
-#endif
+
+ gdb_debug("command='%s'\n", line_buf);
+
p = line_buf;
ch = *p++;
switch(ch) {
@@ -1519,17 +1530,14 @@ static void gdb_read_byte(GDBState *s, int ch)
/* Waiting for a response to the last packet. If we see the start
of a new command then abandon the previous response. */
if (ch == '-') {
-#ifdef DEBUG_GDB
- printf("Got NACK, retransmitting\n");
-#endif
+ gdb_debug("Got NACK, retransmitting\n");
put_buffer(s, (uint8_t *)s->last_packet, s->last_packet_len);
+ } else if (ch == '+') {
+ gdb_debug("Got ACK\n");
+ } else {
+ gdb_debug("Got '%c' when expecting ACK/NACK\n", ch);
}
-#ifdef DEBUG_GDB
- else if (ch == '+')
- printf("Got ACK\n");
- else
- printf("Got '%c' when expecting ACK/NACK\n", ch);
-#endif
+
if (ch == '+' || ch == '$')
s->last_packet_len = 0;
if (ch != '$')
@@ -1550,9 +1558,7 @@ static void gdb_read_byte(GDBState *s, int ch)
s->line_sum = 0;
s->state = RS_GETLINE;
} else {
-#ifdef DEBUG_GDB
- printf("gdbstub received garbage between packets: 0x%x\n", ch);
-#endif
+ gdb_debug("received garbage between packets: 0x%x\n", ch);
}
break;
case RS_GETLINE:
@@ -1568,9 +1574,7 @@ static void gdb_read_byte(GDBState *s, int ch)
/* end of command, start of checksum*/
s->state = RS_CHKSUM1;
} else if (s->line_buf_index >= sizeof(s->line_buf) - 1) {
-#ifdef DEBUG_GDB
- printf("gdbstub command buffer overrun, dropping command\n");
-#endif
+ gdb_debug("command buffer overrun, dropping command\n");
s->state = RS_IDLE;
} else {
/* unescaped command character */
@@ -1584,9 +1588,7 @@ static void gdb_read_byte(GDBState *s, int ch)
s->state = RS_CHKSUM1;
} else if (s->line_buf_index >= sizeof(s->line_buf) - 1) {
/* command buffer overrun */
-#ifdef DEBUG_GDB
- printf("gdbstub command buffer overrun, dropping command\n");
-#endif
+ gdb_debug("command buffer overrun, dropping command\n");
s->state = RS_IDLE;
} else {
/* parse escaped character and leave escape state */
@@ -1598,25 +1600,18 @@ static void gdb_read_byte(GDBState *s, int ch)
case RS_GETLINE_RLE:
if (ch < ' ') {
/* invalid RLE count encoding */
-#ifdef DEBUG_GDB
- printf("gdbstub got invalid RLE count: 0x%x\n", ch);
-#endif
+ gdb_debug("got invalid RLE count: 0x%x\n", ch);
s->state = RS_GETLINE;
} else {
/* decode repeat length */
int repeat = (unsigned char)ch - ' ' + 3;
if (s->line_buf_index + repeat >= sizeof(s->line_buf) - 1) {
/* that many repeats would overrun the command buffer */
-#ifdef DEBUG_GDB
- printf("gdbstub command buffer overrun,"
- " dropping command\n");
-#endif
+ gdb_debug("command buffer overrun, dropping command\n");
s->state = RS_IDLE;
} else if (s->line_buf_index < 1) {
/* got a repeat but we have nothing to repeat */
-#ifdef DEBUG_GDB
- printf("gdbstub got invalid RLE sequence\n");
-#endif
+ gdb_debug("got invalid RLE sequence\n");
s->state = RS_GETLINE;
} else {
/* repeat the last character */
@@ -1631,9 +1626,7 @@ static void gdb_read_byte(GDBState *s, int ch)
case RS_CHKSUM1:
/* get high hex digit of checksum */
if (!isxdigit(ch)) {
-#ifdef DEBUG_GDB
- printf("gdbstub got invalid command checksum digit\n");
-#endif
+ gdb_debug("got invalid command checksum digit\n");
s->state = RS_GETLINE;
break;
}
@@ -1644,21 +1637,17 @@ static void gdb_read_byte(GDBState *s, int ch)
case RS_CHKSUM2:
/* get low hex digit of checksum */
if (!isxdigit(ch)) {
-#ifdef DEBUG_GDB
- printf("gdbstub got invalid command checksum digit\n");
-#endif
+ gdb_debug("got invalid command checksum digit\n");
s->state = RS_GETLINE;
break;
}
s->line_csum |= fromhex(ch);
if (s->line_csum != (s->line_sum & 0xff)) {
+ gdb_debug("got command packet with incorrect checksum\n");
/* send NAK reply */
reply = '-';
put_buffer(s, &reply, 1);
-#ifdef DEBUG_GDB
- printf("gdbstub got command packet with incorrect checksum\n");
-#endif
s->state = RS_IDLE;
} else {
/* send ACK reply */
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 25/41] gdbstub: rename cpu_index -> cpu_gdb_index
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (23 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 24/41] gdbstub: modernise DEBUG_GDB Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 26/41] qom/cpu: remove host_tid field Paolo Bonzini
` (16 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée
From: Alex Bennée <alex.bennee@linaro.org>
This is to make it clear the index is purely a gdbstub function and
should not be confused with the value of cpu->cpu_index. At the same
time we move the function from the header to gdbstub itself which will
help with later changes.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170712105216.747-3-alex.bennee@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
gdbstub.c | 26 ++++++++++++++++++++------
include/exec/gdbstub.h | 9 ---------
2 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/gdbstub.c b/gdbstub.c
index 3965980..b1efe0b 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -56,6 +56,20 @@ static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr,
return cpu_memory_rw_debug(cpu, addr, buf, len, is_write);
}
+/* Return the GDB index for a given vCPU state.
+ *
+ * For user mode this is simply the thread id. In system mode GDB
+ * numbers CPUs from 1 as 0 is reserved as an "any cpu" index.
+ */
+static inline int cpu_gdb_index(CPUState *cpu)
+{
+#if defined(CONFIG_USER_ONLY)
+ return cpu->host_tid;
+#else
+ return cpu->cpu_index + 1;
+#endif
+}
+
enum {
GDB_SIGNAL_0 = 0,
GDB_SIGNAL_INT = 2,
@@ -838,7 +852,7 @@ static CPUState *find_cpu(uint32_t thread_id)
CPUState *cpu;
CPU_FOREACH(cpu) {
- if (cpu_index(cpu) == thread_id) {
+ if (cpu_gdb_index(cpu) == thread_id) {
return cpu;
}
}
@@ -926,7 +940,7 @@ static int gdb_handle_vcont(GDBState *s, const char *p)
idx = tmp;
/* 0 means any thread, so we pick the first valid CPU */
if (!idx) {
- idx = cpu_index(first_cpu);
+ idx = cpu_gdb_index(first_cpu);
}
/*
@@ -976,7 +990,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
case '?':
/* TODO: Make this return the correct value for user-mode. */
snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP,
- cpu_index(s->c_cpu));
+ cpu_gdb_index(s->c_cpu));
put_packet(s, buf);
/* Remove all the breakpoints when this query is issued,
* because gdb is doing and initial connect and the state
@@ -1244,7 +1258,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
} else if (strcmp(p,"sThreadInfo") == 0) {
report_cpuinfo:
if (s->query_cpu) {
- snprintf(buf, sizeof(buf), "m%x", cpu_index(s->query_cpu));
+ snprintf(buf, sizeof(buf), "m%x", cpu_gdb_index(s->query_cpu));
put_packet(s, buf);
s->query_cpu = CPU_NEXT(s->query_cpu);
} else
@@ -1401,7 +1415,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
}
snprintf(buf, sizeof(buf),
"T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
- GDB_SIGNAL_TRAP, cpu_index(cpu), type,
+ GDB_SIGNAL_TRAP, cpu_gdb_index(cpu), type,
(target_ulong)cpu->watchpoint_hit->vaddr);
cpu->watchpoint_hit = NULL;
goto send_packet;
@@ -1435,7 +1449,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
break;
}
gdb_set_stop_cpu(cpu);
- snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(cpu));
+ snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_gdb_index(cpu));
send_packet:
put_packet(s, buf);
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index f9708bb..9aa7756 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -58,15 +58,6 @@ void gdb_register_coprocessor(CPUState *cpu,
gdb_reg_cb get_reg, gdb_reg_cb set_reg,
int num_regs, const char *xml, int g_pos);
-static inline int cpu_index(CPUState *cpu)
-{
-#if defined(CONFIG_USER_ONLY)
- return cpu->host_tid;
-#else
- return cpu->cpu_index + 1;
-#endif
-}
-
/* The GDB remote protocol transfers values in target byte order. This means
* we can use the raw memory access routines to access the value buffer.
* Conveniently, these also handle the case where the buffer is mis-aligned.
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 26/41] qom/cpu: remove host_tid field
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (24 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 25/41] gdbstub: rename cpu_index -> cpu_gdb_index Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 27/41] gdbstub: don't fail on vCont; C04:0; c packets Paolo Bonzini
` (15 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée
From: Alex Bennée <alex.bennee@linaro.org>
This was only used by the gdbstub and even then was only being set for
subsequent threads. Rather the continue duplicating the number just
make the gdbstub get the information from TaskState structure.
Now the tid is correctly reported for all threads the bug I was seeing
with "vCont;C04:0;c" packets is fixed as the correct tid is reported
to gdb.
I moved cpu_gdb_index into the gdbstub to facilitate easy access to
the TaskState which is used elsewhere in gdbstub.
To prevent BSD failing to build I've included ts_tid into its
TaskStruct but not populated it - which was the same state as the old
cpu->host_tid. I'll leave it up to the BSD maintainers to actually
populate this properly if they want a working gdbstub with
user-threads.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20170712105216.747-4-alex.bennee@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
bsd-user/qemu.h | 2 ++
gdbstub.c | 3 ++-
include/qom/cpu.h | 2 --
linux-user/syscall.c | 1 -
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index b550cee..19b2b8f 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -85,6 +85,8 @@ struct emulated_sigtable {
/* NOTE: we force a big alignment so that the stack stored after is
aligned too */
typedef struct TaskState {
+ pid_t ts_tid; /* tid (or pid) of this task */
+
struct TaskState *next;
int used; /* non zero if used */
struct image_info *info;
diff --git a/gdbstub.c b/gdbstub.c
index b1efe0b..378fdd8 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -64,7 +64,8 @@ static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr,
static inline int cpu_gdb_index(CPUState *cpu)
{
#if defined(CONFIG_USER_ONLY)
- return cpu->host_tid;
+ TaskState *ts = (TaskState *) cpu->opaque;
+ return ts->ts_tid;
#else
return cpu->cpu_index + 1;
#endif
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 7bfd50c..d3c783b 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -265,7 +265,6 @@ struct qemu_work_item;
* @cpu_index: CPU index (informative).
* @nr_cores: Number of cores within this CPU package.
* @nr_threads: Number of threads within this CPU.
- * @host_tid: Host thread ID.
* @running: #true if CPU is currently running (lockless).
* @has_waiter: #true if a CPU is currently waiting for the cpu_exec_end;
* valid under cpu_list_lock.
@@ -319,7 +318,6 @@ struct CPUState {
HANDLE hThread;
#endif
int thread_id;
- uint32_t host_tid;
bool running, has_waiter;
struct QemuCond *halt_cond;
bool thread_kicked;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 925ae11..003943b 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6219,7 +6219,6 @@ static void *clone_func(void *arg)
thread_cpu = cpu;
ts = (TaskState *)cpu->opaque;
info->tid = gettid();
- cpu->host_tid = info->tid;
task_settid(ts);
if (info->child_tidptr)
put_user_u32(info->tid, info->child_tidptr);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 27/41] gdbstub: don't fail on vCont; C04:0; c packets
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (25 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 26/41] qom/cpu: remove host_tid field Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 28/41] chardev: fix parallel device can't be reconnect Paolo Bonzini
` (14 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée
From: Alex Bennée <alex.bennee@linaro.org>
The thread-id of 0 means any CPU but we then ignore the fact we find
the first_cpu in this case who can have an index of 0. Instead of
bailing out just test if we have managed to match up thread-id to a
CPU.
Otherwise you get:
gdb_handle_packet: command='vCont;C04:0;c'
put_packet: reply='E22'
The actual reason for gdb sending vCont;C04:0;c was fixed in a
previous commit where we ensure the first_cpu's tid is correctly
reported to gdb however we should still behave correctly next time it
does send 0.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170712105216.747-5-alex.bennee@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
gdbstub.c | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/gdbstub.c b/gdbstub.c
index 378fdd8..f936ddd 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -938,23 +938,16 @@ static int gdb_handle_vcont(GDBState *s, const char *p)
if (res) {
goto out;
}
- idx = tmp;
+
/* 0 means any thread, so we pick the first valid CPU */
- if (!idx) {
- idx = cpu_gdb_index(first_cpu);
- }
+ cpu = tmp ? find_cpu(tmp) : first_cpu;
- /*
- * If we are in user mode, the thread specified is actually a
- * thread id, and not an index. We need to find the actual
- * CPU first, and only then we can use its index.
- */
- cpu = find_cpu(idx);
/* invalid CPU/thread specified */
- if (!idx || !cpu) {
+ if (!cpu) {
res = -EINVAL;
goto out;
}
+
/* only use if no previous match occourred */
if (newstates[cpu->cpu_index] == 1) {
newstates[cpu->cpu_index] = cur_action;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 28/41] chardev: fix parallel device can't be reconnect
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (26 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 27/41] gdbstub: don't fail on vCont; C04:0; c packets Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 29/41] memory/iommu: QOM'fy IOMMU MemoryRegion Paolo Bonzini
` (13 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Peng Hao
From: Peng Hao <peng.hao2@zte.com.cn>
Parallel device don't register be->chr_can_read function, but remote
disconnect event is handled in chr_read.So connected parallel device
can not detect remote disconnect event. The chardevs with chr_can_read=NULL
has the same problem.
Signed-off-by: Peng Hao <peng.hao2@zte.com.cn>
Reviewed-by: Wang Yechao <wang.yechao255@zte.com.cn>
Reviewed-by: Jiang Biao <jiang.biao2@zte.com.cn>
Message-Id: <1499874119-67558-1-git-send-email-peng.hao2@zte.com.cn>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/char/parallel.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/hw/char/parallel.c b/hw/char/parallel.c
index 055789f..f79dc76 100644
--- a/hw/char/parallel.c
+++ b/hw/char/parallel.c
@@ -503,6 +503,10 @@ static const VMStateDescription vmstate_parallel_isa = {
}
};
+static int parallel_can_receive(void *opaque)
+{
+ return 1;
+}
static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
{
@@ -535,6 +539,8 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
isa_init_irq(isadev, &s->irq, isa->isairq);
qemu_register_reset(parallel_reset, s);
+ qemu_chr_fe_set_handlers(&s->chr, parallel_can_receive, NULL,
+ NULL, NULL, s, NULL, true);
if (qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0) {
s->hw_driver = 1;
s->status = dummy;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 29/41] memory/iommu: QOM'fy IOMMU MemoryRegion
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (27 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 28/41] chardev: fix parallel device can't be reconnect Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 30/41] memory/iommu: introduce IOMMUMemoryRegionClass Paolo Bonzini
` (12 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy
From: Alexey Kardashevskiy <aik@ozlabs.ru>
This defines new QOM object - IOMMUMemoryRegion - with MemoryRegion
as a parent.
This moves IOMMU-related fields from MR to IOMMU MR. However to avoid
dymanic QOM casting in fast path (address_space_translate, etc),
this adds an @is_iommu boolean flag to MR and provides new helper to
do simple cast to IOMMU MR - memory_region_get_iommu. The flag
is set in the instance init callback. This defines
memory_region_is_iommu as memory_region_get_iommu()!=NULL.
This switches MemoryRegion to IOMMUMemoryRegion in most places except
the ones where MemoryRegion may be an alias.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20170711035620.4232-2-aik@ozlabs.ru>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
exec.c | 12 ++---
hw/alpha/typhoon.c | 8 ++--
hw/dma/rc4030.c | 8 ++--
hw/i386/amd_iommu.c | 9 ++--
hw/i386/intel_iommu.c | 17 +++----
hw/mips/mips_jazz.c | 2 +-
hw/pci-host/apb.c | 6 +--
hw/ppc/spapr_iommu.c | 16 ++++---
hw/s390x/s390-pci-bus.c | 6 +--
hw/s390x/s390-pci-bus.h | 2 +-
hw/s390x/s390-pci-inst.c | 8 ++--
hw/vfio/common.c | 12 +++--
hw/vfio/spapr.c | 3 +-
include/exec/memory.h | 55 ++++++++++++++--------
include/hw/i386/intel_iommu.h | 2 +-
include/hw/mips/mips.h | 2 +-
include/hw/ppc/spapr.h | 3 +-
include/hw/vfio/vfio-common.h | 2 +-
include/qemu/typedefs.h | 1 +
memory.c | 105 ++++++++++++++++++++++++++++--------------
20 files changed, 170 insertions(+), 109 deletions(-)
diff --git a/exec.c b/exec.c
index 2e8bc43..2aa8be5 100644
--- a/exec.c
+++ b/exec.c
@@ -480,19 +480,19 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
{
IOMMUTLBEntry iotlb;
MemoryRegionSection *section;
- MemoryRegion *mr;
+ IOMMUMemoryRegion *iommu_mr;
for (;;) {
AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
section = address_space_translate_internal(d, addr, &addr, plen, is_mmio);
- mr = section->mr;
- if (!mr->iommu_ops) {
+ iommu_mr = memory_region_get_iommu(section->mr);
+ if (!iommu_mr) {
break;
}
- iotlb = mr->iommu_ops->translate(mr, addr, is_write ?
- IOMMU_WO : IOMMU_RO);
+ iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, is_write ?
+ IOMMU_WO : IOMMU_RO);
addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
| (addr & iotlb.addr_mask));
*plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
@@ -588,7 +588,7 @@ address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr,
section = address_space_translate_internal(d, addr, xlat, plen, false);
- assert(!section->mr->iommu_ops);
+ assert(!memory_region_is_iommu(section->mr));
return section;
}
#endif
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index c1cf780..dd47b45 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -41,7 +41,7 @@ typedef struct TyphoonPchip {
MemoryRegion reg_conf;
AddressSpace iommu_as;
- MemoryRegion iommu;
+ IOMMUMemoryRegion iommu;
uint64_t ctl;
TyphoonWindow win[4];
@@ -663,7 +663,8 @@ static bool window_translate(TyphoonWindow *win, hwaddr addr,
/* Handle PCI-to-system address translation. */
/* TODO: A translation failure here ought to set PCI error codes on the
Pchip and generate a machine check interrupt. */
-static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr,
+static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu,
+ hwaddr addr,
IOMMUAccessFlags flag)
{
TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
@@ -893,7 +894,8 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
/* Host memory as seen from the PCI side, via the IOMMU. */
memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops,
"iommu-typhoon", UINT64_MAX);
- address_space_init(&s->pchip.iommu_as, &s->pchip.iommu, "pchip0-pci");
+ address_space_init(&s->pchip.iommu_as, MEMORY_REGION(&s->pchip.iommu),
+ "pchip0-pci");
pci_setup_iommu(b, typhoon_pci_dma_iommu, s);
/* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB. */
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index edf9432..32c0676 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -90,7 +90,7 @@ typedef struct rc4030State
qemu_irq jazz_bus_irq;
/* whole DMA memory region, root of DMA address space */
- MemoryRegion dma_mr;
+ IOMMUMemoryRegion dma_mr;
AddressSpace dma_as;
MemoryRegion iomem_chipset;
@@ -488,7 +488,7 @@ static const MemoryRegionOps jazzio_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr addr,
+static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag)
{
rc4030State *s = container_of(iommu, rc4030State, dma_mr);
@@ -679,7 +679,7 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
"rc4030.dma", UINT32_MAX);
- address_space_init(&s->dma_as, &s->dma_mr, "rc4030-dma");
+ address_space_init(&s->dma_as, MEMORY_REGION(&s->dma_mr), "rc4030-dma");
}
static void rc4030_unrealize(DeviceState *dev, Error **errp)
@@ -717,7 +717,7 @@ static void rc4030_register_types(void)
type_init(rc4030_register_types)
-DeviceState *rc4030_init(rc4030_dma **dmas, MemoryRegion **dma_mr)
+DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr)
{
DeviceState *dev;
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index d93ffc2..7a67c57 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -52,7 +52,7 @@ struct AMDVIAddressSpace {
uint8_t bus_num; /* bus number */
uint8_t devfn; /* device function */
AMDVIState *iommu_state; /* AMDVI - one per machine */
- MemoryRegion iommu; /* Device's address translation region */
+ IOMMUMemoryRegion iommu; /* Device's address translation region */
MemoryRegion iommu_ir; /* Device's interrupt remapping region */
AddressSpace as; /* device's corresponding address space */
};
@@ -987,7 +987,7 @@ static inline bool amdvi_is_interrupt_addr(hwaddr addr)
return addr >= AMDVI_INT_ADDR_FIRST && addr <= AMDVI_INT_ADDR_LAST;
}
-static IOMMUTLBEntry amdvi_translate(MemoryRegion *iommu, hwaddr addr,
+static IOMMUTLBEntry amdvi_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag)
{
AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu);
@@ -1046,7 +1046,8 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
memory_region_init_iommu(&iommu_as[devfn]->iommu, OBJECT(s),
&s->iommu_ops, "amd-iommu", UINT64_MAX);
- address_space_init(&iommu_as[devfn]->as, &iommu_as[devfn]->iommu,
+ address_space_init(&iommu_as[devfn]->as,
+ MEMORY_REGION(&iommu_as[devfn]->iommu),
"amd-iommu");
}
return &iommu_as[devfn]->as;
@@ -1067,7 +1068,7 @@ static const MemoryRegionOps mmio_mem_ops = {
}
};
-static void amdvi_iommu_notify_flag_changed(MemoryRegion *iommu,
+static void amdvi_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
IOMMUNotifierFlag old,
IOMMUNotifierFlag new)
{
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 88dc042..11dba0e 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -972,9 +972,9 @@ static bool vtd_switch_address_space(VTDAddressSpace *as)
/* Turn off first then on the other */
if (use_iommu) {
memory_region_set_enabled(&as->sys_alias, false);
- memory_region_set_enabled(&as->iommu, true);
+ memory_region_set_enabled(MEMORY_REGION(&as->iommu), true);
} else {
- memory_region_set_enabled(&as->iommu, false);
+ memory_region_set_enabled(MEMORY_REGION(&as->iommu), false);
memory_region_set_enabled(&as->sys_alias, true);
}
@@ -1366,7 +1366,7 @@ static void vtd_iotlb_domain_invalidate(IntelIOMMUState *s, uint16_t domain_id)
static int vtd_page_invalidate_notify_hook(IOMMUTLBEntry *entry,
void *private)
{
- memory_region_notify_iommu((MemoryRegion *)private, *entry);
+ memory_region_notify_iommu((IOMMUMemoryRegion *)private, *entry);
return 0;
}
@@ -2264,7 +2264,7 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
}
}
-static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
+static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag)
{
VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
@@ -2303,7 +2303,7 @@ static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
return iotlb;
}
-static void vtd_iommu_notify_flag_changed(MemoryRegion *iommu,
+static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
IOMMUNotifierFlag old,
IOMMUNotifierFlag new)
{
@@ -2736,7 +2736,8 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
memory_region_add_subregion_overlap(&vtd_dev_as->root, 0,
&vtd_dev_as->sys_alias, 1);
memory_region_add_subregion_overlap(&vtd_dev_as->root, 0,
- &vtd_dev_as->iommu, 1);
+ MEMORY_REGION(&vtd_dev_as->iommu),
+ 1);
vtd_switch_address_space(vtd_dev_as);
}
return vtd_dev_as;
@@ -2816,9 +2817,9 @@ static int vtd_replay_hook(IOMMUTLBEntry *entry, void *private)
return 0;
}
-static void vtd_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
+static void vtd_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
{
- VTDAddressSpace *vtd_as = container_of(mr, VTDAddressSpace, iommu);
+ VTDAddressSpace *vtd_as = container_of(iommu_mr, VTDAddressSpace, iommu);
IntelIOMMUState *s = vtd_as->iommu_state;
uint8_t bus_n = pci_bus_num(vtd_as->bus);
VTDContextEntry ce;
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 1cef581..1f69322 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -130,7 +130,7 @@ static void mips_jazz_init(MachineState *machine,
CPUMIPSState *env;
qemu_irq *i8259;
rc4030_dma *dmas;
- MemoryRegion *rc4030_dma_mr;
+ IOMMUMemoryRegion *rc4030_dma_mr;
MemoryRegion *isa_mem = g_new(MemoryRegion, 1);
MemoryRegion *isa_io = g_new(MemoryRegion, 1);
MemoryRegion *rtc = g_new(MemoryRegion, 1);
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 326f5ef..76a56ae 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -123,7 +123,7 @@ do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
typedef struct IOMMUState {
AddressSpace iommu_as;
- MemoryRegion iommu;
+ IOMMUMemoryRegion iommu;
uint64_t regs[IOMMU_NREGS];
} IOMMUState;
@@ -208,7 +208,7 @@ static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
}
/* Called from RCU critical section */
-static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
+static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag)
{
IOMMUState *is = container_of(iommu, IOMMUState, iommu);
@@ -699,7 +699,7 @@ PCIBus *pci_apb_init(hwaddr special_base,
memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops,
"iommu-apb", UINT64_MAX);
- address_space_init(&is->iommu_as, &is->iommu, "pbm-as");
+ address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as");
pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
/* APB secondary busses */
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 8656a54..6b6ced5 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -110,7 +110,8 @@ static void spapr_tce_free_table(uint64_t *table, int fd, uint32_t nb_table)
}
/* Called from RCU critical section */
-static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
+static IOMMUTLBEntry spapr_tce_translate_iommu(IOMMUMemoryRegion *iommu,
+ hwaddr addr,
IOMMUAccessFlags flag)
{
sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
@@ -150,14 +151,14 @@ static void spapr_tce_table_pre_save(void *opaque)
tcet->bus_offset, tcet->page_shift);
}
-static uint64_t spapr_tce_get_min_page_size(MemoryRegion *iommu)
+static uint64_t spapr_tce_get_min_page_size(IOMMUMemoryRegion *iommu)
{
sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
return 1ULL << tcet->page_shift;
}
-static void spapr_tce_notify_flag_changed(MemoryRegion *iommu,
+static void spapr_tce_notify_flag_changed(IOMMUMemoryRegion *iommu,
IOMMUNotifierFlag old,
IOMMUNotifierFlag new)
{
@@ -348,9 +349,10 @@ void spapr_tce_table_enable(sPAPRTCETable *tcet,
&tcet->fd,
tcet->need_vfio);
- memory_region_set_size(&tcet->iommu,
+ memory_region_set_size(MEMORY_REGION(&tcet->iommu),
(uint64_t)tcet->nb_table << tcet->page_shift);
- memory_region_add_subregion(&tcet->root, tcet->bus_offset, &tcet->iommu);
+ memory_region_add_subregion(&tcet->root, tcet->bus_offset,
+ MEMORY_REGION(&tcet->iommu));
}
void spapr_tce_table_disable(sPAPRTCETable *tcet)
@@ -359,8 +361,8 @@ void spapr_tce_table_disable(sPAPRTCETable *tcet)
return;
}
- memory_region_del_subregion(&tcet->root, &tcet->iommu);
- memory_region_set_size(&tcet->iommu, 0);
+ memory_region_del_subregion(&tcet->root, MEMORY_REGION(&tcet->iommu));
+ memory_region_set_size(MEMORY_REGION(&tcet->iommu), 0);
spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table);
tcet->fd = -1;
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 5651483..e4fc82c 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -356,7 +356,7 @@ out:
return pte;
}
-static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *mr, hwaddr addr,
+static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr,
IOMMUAccessFlags flag)
{
uint64_t pte;
@@ -525,14 +525,14 @@ void s390_pci_iommu_enable(S390PCIIOMMU *iommu)
memory_region_init_iommu(&iommu->iommu_mr, OBJECT(&iommu->mr),
&s390_iommu_ops, name, iommu->pal + 1);
iommu->enabled = true;
- memory_region_add_subregion(&iommu->mr, 0, &iommu->iommu_mr);
+ memory_region_add_subregion(&iommu->mr, 0, MEMORY_REGION(&iommu->iommu_mr));
g_free(name);
}
void s390_pci_iommu_disable(S390PCIIOMMU *iommu)
{
iommu->enabled = false;
- memory_region_del_subregion(&iommu->mr, &iommu->iommu_mr);
+ memory_region_del_subregion(&iommu->mr, MEMORY_REGION(&iommu->iommu_mr));
object_unparent(OBJECT(&iommu->iommu_mr));
}
diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
index cf142a3..6a599ed 100644
--- a/hw/s390x/s390-pci-bus.h
+++ b/hw/s390x/s390-pci-bus.h
@@ -266,7 +266,7 @@ typedef struct S390PCIIOMMU {
S390PCIBusDevice *pbdev;
AddressSpace as;
MemoryRegion mr;
- MemoryRegion iommu_mr;
+ IOMMUMemoryRegion iommu_mr;
bool enabled;
uint64_t g_iota;
uint64_t pba;
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 8bc7c98..a53c29c 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -563,7 +563,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
S390PCIIOMMU *iommu;
hwaddr start, end;
IOMMUTLBEntry entry;
- MemoryRegion *mr;
+ IOMMUMemoryRegion *iommu_mr;
cpu_synchronize_state(CPU(cpu));
@@ -622,9 +622,9 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
goto out;
}
- mr = &iommu->iommu_mr;
+ iommu_mr = &iommu->iommu_mr;
while (start < end) {
- entry = mr->iommu_ops->translate(mr, start, IOMMU_NONE);
+ entry = iommu_mr->iommu_ops->translate(iommu_mr, start, IOMMU_NONE);
if (!entry.translated_addr) {
pbdev->state = ZPCI_FS_ERROR;
@@ -635,7 +635,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
goto out;
}
- memory_region_notify_iommu(mr, entry);
+ memory_region_notify_iommu(iommu_mr, entry);
start += entry.addr_mask + 1;
}
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 29923e4..c1bb6d4 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -479,6 +479,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
if (memory_region_is_iommu(section->mr)) {
VFIOGuestIOMMU *giommu;
+ IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
trace_vfio_listener_region_add_iommu(iova, end);
/*
@@ -488,7 +489,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
* device emulation the VFIO iommu handles to use).
*/
giommu = g_malloc0(sizeof(*giommu));
- giommu->iommu = section->mr;
+ giommu->iommu = iommu_mr;
giommu->iommu_offset = section->offset_within_address_space -
section->offset_within_region;
giommu->container = container;
@@ -501,7 +502,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
int128_get64(llend));
QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
- memory_region_register_iommu_notifier(giommu->iommu, &giommu->n);
+ memory_region_register_iommu_notifier(section->mr, &giommu->n);
memory_region_iommu_replay(giommu->iommu, &giommu->n);
return;
@@ -569,9 +570,9 @@ static void vfio_listener_region_del(MemoryListener *listener,
VFIOGuestIOMMU *giommu;
QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) {
- if (giommu->iommu == section->mr &&
+ if (MEMORY_REGION(giommu->iommu) == section->mr &&
giommu->n.start == section->offset_within_region) {
- memory_region_unregister_iommu_notifier(giommu->iommu,
+ memory_region_unregister_iommu_notifier(section->mr,
&giommu->n);
QLIST_REMOVE(giommu, giommu_next);
g_free(giommu);
@@ -1163,7 +1164,8 @@ static void vfio_disconnect_container(VFIOGroup *group)
QLIST_REMOVE(container, next);
QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) {
- memory_region_unregister_iommu_notifier(giommu->iommu, &giommu->n);
+ memory_region_unregister_iommu_notifier(
+ MEMORY_REGION(giommu->iommu), &giommu->n);
QLIST_REMOVE(giommu, giommu_next);
g_free(giommu);
}
diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c
index 4409bcc..32fd6a9 100644
--- a/hw/vfio/spapr.c
+++ b/hw/vfio/spapr.c
@@ -143,7 +143,8 @@ int vfio_spapr_create_window(VFIOContainer *container,
hwaddr *pgsize)
{
int ret;
- unsigned pagesize = memory_region_iommu_get_min_page_size(section->mr);
+ IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
+ unsigned pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
unsigned entries, pages;
struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) };
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 8503685..92980ab 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -35,6 +35,10 @@
#define MEMORY_REGION(obj) \
OBJECT_CHECK(MemoryRegion, (obj), TYPE_MEMORY_REGION)
+#define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region"
+#define IOMMU_MEMORY_REGION(obj) \
+ OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_IOMMU_MEMORY_REGION)
+
typedef struct MemoryRegionOps MemoryRegionOps;
typedef struct MemoryRegionMmio MemoryRegionMmio;
@@ -198,16 +202,16 @@ struct MemoryRegionIOMMUOps {
* set flag to IOMMU_NONE to mean that we don't need any
* read/write permission checks, like, when for region replay.
*/
- IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr,
+ IOMMUTLBEntry (*translate)(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag);
/* Returns minimum supported page size */
- uint64_t (*get_min_page_size)(MemoryRegion *iommu);
+ uint64_t (*get_min_page_size)(IOMMUMemoryRegion *iommu);
/* Called when IOMMU Notifier flag changed */
- void (*notify_flag_changed)(MemoryRegion *iommu,
+ void (*notify_flag_changed)(IOMMUMemoryRegion *iommu,
IOMMUNotifierFlag old_flags,
IOMMUNotifierFlag new_flags);
/* Set this up to provide customized IOMMU replay function */
- void (*replay)(MemoryRegion *iommu, IOMMUNotifier *notifier);
+ void (*replay)(IOMMUMemoryRegion *iommu, IOMMUNotifier *notifier);
};
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
@@ -227,9 +231,9 @@ struct MemoryRegion {
bool flush_coalesced_mmio;
bool global_locking;
uint8_t dirty_log_mask;
+ bool is_iommu;
RAMBlock *ram_block;
Object *owner;
- const MemoryRegionIOMMUOps *iommu_ops;
const MemoryRegionOps *ops;
void *opaque;
@@ -252,6 +256,12 @@ struct MemoryRegion {
const char *name;
unsigned ioeventfd_nb;
MemoryRegionIoeventfd *ioeventfds;
+};
+
+struct IOMMUMemoryRegion {
+ MemoryRegion parent_obj;
+
+ const MemoryRegionIOMMUOps *iommu_ops;
QLIST_HEAD(, IOMMUNotifier) iommu_notify;
IOMMUNotifierFlag iommu_notify_flags;
};
@@ -618,13 +628,13 @@ static inline void memory_region_init_reservation(MemoryRegion *mr,
* An IOMMU region translates addresses and forwards accesses to a target
* memory region.
*
- * @mr: the #MemoryRegion to be initialized
+ * @iommu_mr: the #IOMMUMemoryRegion to be initialized
* @owner: the object that tracks the region's reference count
* @ops: a function that translates addresses into the @target region
* @name: used for debugging; not visible to the user or ABI
* @size: size of the region.
*/
-void memory_region_init_iommu(MemoryRegion *mr,
+void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
struct Object *owner,
const MemoryRegionIOMMUOps *ops,
const char *name,
@@ -679,20 +689,25 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
}
/**
- * memory_region_is_iommu: check whether a memory region is an iommu
+ * memory_region_get_iommu: check whether a memory region is an iommu
*
- * Returns %true is a memory region is an iommu.
+ * Returns pointer to IOMMUMemoryRegion if a memory region is an iommu,
+ * otherwise NULL.
*
* @mr: the memory region being queried
*/
-static inline bool memory_region_is_iommu(MemoryRegion *mr)
+static inline IOMMUMemoryRegion *memory_region_get_iommu(MemoryRegion *mr)
{
if (mr->alias) {
- return memory_region_is_iommu(mr->alias);
+ return memory_region_get_iommu(mr->alias);
+ }
+ if (mr->is_iommu) {
+ return (IOMMUMemoryRegion *) mr;
}
- return mr->iommu_ops;
+ return NULL;
}
+#define memory_region_is_iommu(mr) (memory_region_get_iommu(mr) != NULL)
/**
* memory_region_iommu_get_min_page_size: get minimum supported page size
@@ -700,9 +715,9 @@ static inline bool memory_region_is_iommu(MemoryRegion *mr)
*
* Returns minimum supported page size for an iommu.
*
- * @mr: the memory region being queried
+ * @iommu_mr: the memory region being queried
*/
-uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr);
+uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr);
/**
* memory_region_notify_iommu: notify a change in an IOMMU translation entry.
@@ -716,12 +731,12 @@ uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr);
* Note: for any IOMMU implementation, an in-place mapping change
* should be notified with an UNMAP followed by a MAP.
*
- * @mr: the memory region that was changed
+ * @iommu_mr: the memory region that was changed
* @entry: the new entry in the IOMMU translation table. The entry
* replaces all old entries for the same virtual I/O address range.
* Deleted entries have .@perm == 0.
*/
-void memory_region_notify_iommu(MemoryRegion *mr,
+void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
IOMMUTLBEntry entry);
/**
@@ -756,18 +771,18 @@ void memory_region_register_iommu_notifier(MemoryRegion *mr,
* a notifier with the minimum page granularity returned by
* mr->iommu_ops->get_page_size().
*
- * @mr: the memory region to observe
+ * @iommu_mr: the memory region to observe
* @n: the notifier to which to replay iommu mappings
*/
-void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n);
+void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n);
/**
* memory_region_iommu_replay_all: replay existing IOMMU translations
* to all the notifiers registered.
*
- * @mr: the memory region to observe
+ * @iommu_mr: the memory region to observe
*/
-void memory_region_iommu_replay_all(MemoryRegion *mr);
+void memory_region_iommu_replay_all(IOMMUMemoryRegion *iommu_mr);
/**
* memory_region_unregister_iommu_notifier: unregister a notifier for
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 3e51876..45fba4f 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -83,7 +83,7 @@ struct VTDAddressSpace {
PCIBus *bus;
uint8_t devfn;
AddressSpace as;
- MemoryRegion iommu;
+ IOMMUMemoryRegion iommu;
MemoryRegion root;
MemoryRegion sys_alias;
MemoryRegion iommu_ir; /* Interrupt region: 0xfeeXXXXX */
diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h
index 16412dc..2f6774d 100644
--- a/include/hw/mips/mips.h
+++ b/include/hw/mips/mips.h
@@ -19,6 +19,6 @@ typedef struct rc4030DMAState *rc4030_dma;
void rc4030_dma_read(void *dma, uint8_t *buf, int len);
void rc4030_dma_write(void *dma, uint8_t *buf, int len);
-DeviceState *rc4030_init(rc4030_dma **dmas, MemoryRegion **dma_mr);
+DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr);
#endif
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index a184ffa..b353dff 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -594,7 +594,8 @@ struct sPAPRTCETable {
bool bypass;
bool need_vfio;
int fd;
- MemoryRegion root, iommu;
+ MemoryRegion root;
+ IOMMUMemoryRegion iommu;
struct VIOsPAPRDevice *vdev; /* for @bypass migration compatibility only */
QLIST_ENTRY(sPAPRTCETable) list;
};
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 0b475a3..f3a2ac9 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -95,7 +95,7 @@ typedef struct VFIOContainer {
typedef struct VFIOGuestIOMMU {
VFIOContainer *container;
- MemoryRegion *iommu;
+ IOMMUMemoryRegion *iommu;
hwaddr iommu_offset;
IOMMUNotifier n;
QLIST_ENTRY(VFIOGuestIOMMU) giommu_next;
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 2706aab..b191591 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -45,6 +45,7 @@ typedef struct MachineState MachineState;
typedef struct MemoryListener MemoryListener;
typedef struct MemoryMappingList MemoryMappingList;
typedef struct MemoryRegion MemoryRegion;
+typedef struct IOMMUMemoryRegion IOMMUMemoryRegion;
typedef struct MemoryRegionCache MemoryRegionCache;
typedef struct MemoryRegionSection MemoryRegionSection;
typedef struct MigrationIncomingState MigrationIncomingState;
diff --git a/memory.c b/memory.c
index 1044bba..45e10e2 100644
--- a/memory.c
+++ b/memory.c
@@ -977,12 +977,11 @@ static char *memory_region_escape_name(const char *name)
return escaped;
}
-void memory_region_init(MemoryRegion *mr,
- Object *owner,
- const char *name,
- uint64_t size)
+static void memory_region_do_init(MemoryRegion *mr,
+ Object *owner,
+ const char *name,
+ uint64_t size)
{
- object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
mr->size = int128_make64(size);
if (size == UINT64_MAX) {
mr->size = int128_2_64();
@@ -1006,6 +1005,15 @@ void memory_region_init(MemoryRegion *mr,
}
}
+void memory_region_init(MemoryRegion *mr,
+ Object *owner,
+ const char *name,
+ uint64_t size)
+{
+ object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
+ memory_region_do_init(mr, owner, name, size);
+}
+
static void memory_region_get_addr(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -1092,6 +1100,13 @@ static void memory_region_initfn(Object *obj)
NULL, NULL, &error_abort);
}
+static void iommu_memory_region_initfn(Object *obj)
+{
+ MemoryRegion *mr = MEMORY_REGION(obj);
+
+ mr->is_iommu = true;
+}
+
static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
unsigned size)
{
@@ -1491,17 +1506,22 @@ void memory_region_init_rom_device(MemoryRegion *mr,
mr->ram_block = qemu_ram_alloc(size, mr, errp);
}
-void memory_region_init_iommu(MemoryRegion *mr,
+void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
Object *owner,
const MemoryRegionIOMMUOps *ops,
const char *name,
uint64_t size)
{
- memory_region_init(mr, owner, name, size);
- mr->iommu_ops = ops,
+ struct MemoryRegion *mr;
+
+ object_initialize(iommu_mr, sizeof(*iommu_mr), TYPE_IOMMU_MEMORY_REGION);
+ mr = MEMORY_REGION(iommu_mr);
+ memory_region_do_init(mr, owner, name, size);
+ iommu_mr = IOMMU_MEMORY_REGION(mr);
+ iommu_mr->iommu_ops = ops,
mr->terminates = true; /* then re-forwards */
- QLIST_INIT(&mr->iommu_notify);
- mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
+ QLIST_INIT(&iommu_mr->iommu_notify);
+ iommu_mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
}
static void memory_region_finalize(Object *obj)
@@ -1596,63 +1616,67 @@ bool memory_region_is_logging(MemoryRegion *mr, uint8_t client)
return memory_region_get_dirty_log_mask(mr) & (1 << client);
}
-static void memory_region_update_iommu_notify_flags(MemoryRegion *mr)
+static void memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iommu_mr)
{
IOMMUNotifierFlag flags = IOMMU_NOTIFIER_NONE;
IOMMUNotifier *iommu_notifier;
- IOMMU_NOTIFIER_FOREACH(iommu_notifier, mr) {
+ IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
flags |= iommu_notifier->notifier_flags;
}
- if (flags != mr->iommu_notify_flags &&
- mr->iommu_ops->notify_flag_changed) {
- mr->iommu_ops->notify_flag_changed(mr, mr->iommu_notify_flags,
- flags);
+ if (flags != iommu_mr->iommu_notify_flags &&
+ iommu_mr->iommu_ops->notify_flag_changed) {
+ iommu_mr->iommu_ops->notify_flag_changed(iommu_mr,
+ iommu_mr->iommu_notify_flags,
+ flags);
}
- mr->iommu_notify_flags = flags;
+ iommu_mr->iommu_notify_flags = flags;
}
void memory_region_register_iommu_notifier(MemoryRegion *mr,
IOMMUNotifier *n)
{
+ IOMMUMemoryRegion *iommu_mr;
+
if (mr->alias) {
memory_region_register_iommu_notifier(mr->alias, n);
return;
}
/* We need to register for at least one bitfield */
+ iommu_mr = IOMMU_MEMORY_REGION(mr);
assert(n->notifier_flags != IOMMU_NOTIFIER_NONE);
assert(n->start <= n->end);
- QLIST_INSERT_HEAD(&mr->iommu_notify, n, node);
- memory_region_update_iommu_notify_flags(mr);
+ QLIST_INSERT_HEAD(&iommu_mr->iommu_notify, n, node);
+ memory_region_update_iommu_notify_flags(iommu_mr);
}
-uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr)
+uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr)
{
- assert(memory_region_is_iommu(mr));
- if (mr->iommu_ops && mr->iommu_ops->get_min_page_size) {
- return mr->iommu_ops->get_min_page_size(mr);
+ if (iommu_mr->iommu_ops && iommu_mr->iommu_ops->get_min_page_size) {
+ return iommu_mr->iommu_ops->get_min_page_size(iommu_mr);
}
return TARGET_PAGE_SIZE;
}
-void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
+void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
{
+ MemoryRegion *mr = MEMORY_REGION(iommu_mr);
hwaddr addr, granularity;
IOMMUTLBEntry iotlb;
/* If the IOMMU has its own replay callback, override */
- if (mr->iommu_ops->replay) {
- mr->iommu_ops->replay(mr, n);
+ if (iommu_mr->iommu_ops->replay) {
+ iommu_mr->iommu_ops->replay(iommu_mr, n);
return;
}
- granularity = memory_region_iommu_get_min_page_size(mr);
+ granularity = memory_region_iommu_get_min_page_size(iommu_mr);
for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
- iotlb = mr->iommu_ops->translate(mr, addr, IOMMU_NONE);
+ iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, IOMMU_NONE);
if (iotlb.perm != IOMMU_NONE) {
n->notify(n, &iotlb);
}
@@ -1665,24 +1689,27 @@ void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
}
}
-void memory_region_iommu_replay_all(MemoryRegion *mr)
+void memory_region_iommu_replay_all(IOMMUMemoryRegion *iommu_mr)
{
IOMMUNotifier *notifier;
- IOMMU_NOTIFIER_FOREACH(notifier, mr) {
- memory_region_iommu_replay(mr, notifier);
+ IOMMU_NOTIFIER_FOREACH(notifier, iommu_mr) {
+ memory_region_iommu_replay(iommu_mr, notifier);
}
}
void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
IOMMUNotifier *n)
{
+ IOMMUMemoryRegion *iommu_mr;
+
if (mr->alias) {
memory_region_unregister_iommu_notifier(mr->alias, n);
return;
}
QLIST_REMOVE(n, node);
- memory_region_update_iommu_notify_flags(mr);
+ iommu_mr = IOMMU_MEMORY_REGION(mr);
+ memory_region_update_iommu_notify_flags(iommu_mr);
}
void memory_region_notify_one(IOMMUNotifier *notifier,
@@ -1710,14 +1737,14 @@ void memory_region_notify_one(IOMMUNotifier *notifier,
}
}
-void memory_region_notify_iommu(MemoryRegion *mr,
+void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
IOMMUTLBEntry entry)
{
IOMMUNotifier *iommu_notifier;
- assert(memory_region_is_iommu(mr));
+ assert(memory_region_is_iommu(MEMORY_REGION(iommu_mr)));
- IOMMU_NOTIFIER_FOREACH(iommu_notifier, mr) {
+ IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
memory_region_notify_one(iommu_notifier, &entry);
}
}
@@ -2825,9 +2852,17 @@ static const TypeInfo memory_region_info = {
.instance_finalize = memory_region_finalize,
};
+static const TypeInfo iommu_memory_region_info = {
+ .parent = TYPE_MEMORY_REGION,
+ .name = TYPE_IOMMU_MEMORY_REGION,
+ .instance_size = sizeof(IOMMUMemoryRegion),
+ .instance_init = iommu_memory_region_initfn,
+};
+
static void memory_register_types(void)
{
type_register_static(&memory_region_info);
+ type_register_static(&iommu_memory_region_info);
}
type_init(memory_register_types)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 30/41] memory/iommu: introduce IOMMUMemoryRegionClass
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (28 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 29/41] memory/iommu: QOM'fy IOMMU MemoryRegion Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 31/41] nbd: Create struct for tracking export info Paolo Bonzini
` (11 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy
From: Alexey Kardashevskiy <aik@ozlabs.ru>
This finishes QOM'fication of IOMMUMemoryRegion by introducing
a IOMMUMemoryRegionClass. This also provides a fastpath analog for
IOMMU_MEMORY_REGION_GET_CLASS().
This makes IOMMUMemoryRegion an abstract class.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170711035620.4232-3-aik@ozlabs.ru>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
exec.c | 6 ++++--
hw/alpha/typhoon.c | 23 +++++++++++++++++-----
hw/dma/rc4030.c | 26 +++++++++++++++++++------
hw/i386/amd_iommu.c | 24 +++++++++++++++++++----
hw/i386/amd_iommu.h | 5 ++---
hw/i386/intel_iommu.c | 25 +++++++++++++++++++-----
hw/pci-host/apb.c | 23 +++++++++++++++++-----
hw/ppc/spapr_iommu.c | 26 ++++++++++++++++++-------
hw/s390x/s390-pci-bus.c | 23 ++++++++++++++++------
hw/s390x/s390-pci-bus.h | 1 +
hw/s390x/s390-pci-inst.c | 5 ++++-
include/exec/memory.h | 45 +++++++++++++++++++++++++++++++++----------
include/hw/i386/intel_iommu.h | 3 ++-
include/hw/ppc/spapr.h | 4 ++++
memory.c | 36 +++++++++++++++++++---------------
15 files changed, 205 insertions(+), 70 deletions(-)
diff --git a/exec.c b/exec.c
index 2aa8be5..b3c080f 100644
--- a/exec.c
+++ b/exec.c
@@ -481,6 +481,7 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
IOMMUTLBEntry iotlb;
MemoryRegionSection *section;
IOMMUMemoryRegion *iommu_mr;
+ IOMMUMemoryRegionClass *imrc;
for (;;) {
AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
@@ -490,9 +491,10 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
if (!iommu_mr) {
break;
}
+ imrc = memory_region_get_iommu_class_nocheck(iommu_mr);
- iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, is_write ?
- IOMMU_WO : IOMMU_RO);
+ iotlb = imrc->translate(iommu_mr, addr, is_write ?
+ IOMMU_WO : IOMMU_RO);
addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
| (addr & iotlb.addr_mask));
*plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index dd47b45..ae11e01 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -17,6 +17,7 @@
#define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost"
+#define TYPE_TYPHOON_IOMMU_MEMORY_REGION "typhoon-iommu-memory-region"
typedef struct TyphoonCchip {
MemoryRegion region;
@@ -725,10 +726,6 @@ static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu,
return ret;
}
-static const MemoryRegionIOMMUOps typhoon_iommu_ops = {
- .translate = typhoon_translate_iommu,
-};
-
static AddressSpace *typhoon_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
{
TyphoonState *s = opaque;
@@ -892,7 +889,8 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
qdev_init_nofail(dev);
/* Host memory as seen from the PCI side, via the IOMMU. */
- memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops,
+ memory_region_init_iommu(&s->pchip.iommu, sizeof(s->pchip.iommu),
+ TYPE_TYPHOON_IOMMU_MEMORY_REGION, OBJECT(s),
"iommu-typhoon", UINT64_MAX);
address_space_init(&s->pchip.iommu_as, MEMORY_REGION(&s->pchip.iommu),
"pchip0-pci");
@@ -953,9 +951,24 @@ static const TypeInfo typhoon_pcihost_info = {
.class_init = typhoon_pcihost_class_init,
};
+static void typhoon_iommu_memory_region_class_init(ObjectClass *klass,
+ void *data)
+{
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+ imrc->translate = typhoon_translate_iommu;
+}
+
+static const TypeInfo typhoon_iommu_memory_region_info = {
+ .parent = TYPE_IOMMU_MEMORY_REGION,
+ .name = TYPE_TYPHOON_IOMMU_MEMORY_REGION,
+ .class_init = typhoon_iommu_memory_region_class_init,
+};
+
static void typhoon_register_types(void)
{
type_register_static(&typhoon_pcihost_info);
+ type_register_static(&typhoon_iommu_memory_region_info);
}
type_init(typhoon_register_types)
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index 32c0676..5d4833e 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -54,6 +54,8 @@ typedef struct dma_pagetable_entry {
#define RC4030(obj) \
OBJECT_CHECK(rc4030State, (obj), TYPE_RC4030)
+#define TYPE_RC4030_IOMMU_MEMORY_REGION "rc4030-iommu-memory-region"
+
typedef struct rc4030State
{
SysBusDevice parent;
@@ -516,10 +518,6 @@ static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
return ret;
}
-static const MemoryRegionIOMMUOps rc4030_dma_ops = {
- .translate = rc4030_dma_translate,
-};
-
static void rc4030_reset(DeviceState *dev)
{
rc4030State *s = RC4030(dev);
@@ -677,8 +675,9 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s,
"rc4030.jazzio", 0x00001000);
- memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
- "rc4030.dma", UINT32_MAX);
+ memory_region_init_iommu(&s->dma_mr, sizeof(s->dma_mr),
+ TYPE_RC4030_IOMMU_MEMORY_REGION,
+ o, "rc4030.dma", UINT32_MAX);
address_space_init(&s->dma_as, MEMORY_REGION(&s->dma_mr), "rc4030-dma");
}
@@ -710,9 +709,24 @@ static const TypeInfo rc4030_info = {
.class_init = rc4030_class_init,
};
+static void rc4030_iommu_memory_region_class_init(ObjectClass *klass,
+ void *data)
+{
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+ imrc->translate = rc4030_dma_translate;
+}
+
+static const TypeInfo rc4030_iommu_memory_region_info = {
+ .parent = TYPE_IOMMU_MEMORY_REGION,
+ .name = TYPE_RC4030_IOMMU_MEMORY_REGION,
+ .class_init = rc4030_iommu_memory_region_class_init,
+};
+
static void rc4030_register_types(void)
{
type_register_static(&rc4030_info);
+ type_register_static(&rc4030_iommu_memory_region_info);
}
type_init(rc4030_register_types)
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 7a67c57..334938a 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -1044,8 +1044,11 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
iommu_as[devfn]->devfn = (uint8_t)devfn;
iommu_as[devfn]->iommu_state = s;
- memory_region_init_iommu(&iommu_as[devfn]->iommu, OBJECT(s),
- &s->iommu_ops, "amd-iommu", UINT64_MAX);
+ memory_region_init_iommu(&iommu_as[devfn]->iommu,
+ sizeof(iommu_as[devfn]->iommu),
+ TYPE_AMD_IOMMU_MEMORY_REGION,
+ OBJECT(s),
+ "amd-iommu", UINT64_MAX);
address_space_init(&iommu_as[devfn]->as,
MEMORY_REGION(&iommu_as[devfn]->iommu),
"amd-iommu");
@@ -1086,8 +1089,6 @@ static void amdvi_init(AMDVIState *s)
{
amdvi_iotlb_reset(s);
- s->iommu_ops.translate = amdvi_translate;
- s->iommu_ops.notify_flag_changed = amdvi_iommu_notify_flag_changed;
s->devtab_len = 0;
s->cmdbuf_len = 0;
s->cmdbuf_head = 0;
@@ -1228,10 +1229,25 @@ static const TypeInfo amdviPCI = {
.instance_size = sizeof(AMDVIPCIState),
};
+static void amdvi_iommu_memory_region_class_init(ObjectClass *klass, void *data)
+{
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+ imrc->translate = amdvi_translate;
+ imrc->notify_flag_changed = amdvi_iommu_notify_flag_changed;
+}
+
+static const TypeInfo amdvi_iommu_memory_region_info = {
+ .parent = TYPE_IOMMU_MEMORY_REGION,
+ .name = TYPE_AMD_IOMMU_MEMORY_REGION,
+ .class_init = amdvi_iommu_memory_region_class_init,
+};
+
static void amdviPCI_register_types(void)
{
type_register_static(&amdviPCI);
type_register_static(&amdvi);
+ type_register_static(&amdvi_iommu_memory_region_info);
}
type_init(amdviPCI_register_types);
diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
index 0d3dc6a..d370ae3 100644
--- a/hw/i386/amd_iommu.h
+++ b/hw/i386/amd_iommu.h
@@ -220,6 +220,8 @@
#define TYPE_AMD_IOMMU_PCI "AMDVI-PCI"
+#define TYPE_AMD_IOMMU_MEMORY_REGION "amd-iommu-iommu-memory-region"
+
typedef struct AMDVIAddressSpace AMDVIAddressSpace;
/* functions to steal PCI config space */
@@ -276,9 +278,6 @@ typedef struct AMDVIState {
uint8_t romask[AMDVI_MMIO_SIZE]; /* MMIO read/only mask */
bool mmio_enabled;
- /* IOMMU function */
- MemoryRegionIOMMUOps iommu_ops;
-
/* for each served device */
AMDVIAddressSpace **address_spaces[PCI_BUS_MAX];
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 11dba0e..e398746 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2718,8 +2718,9 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
* vtd_sys_alias and intel_iommu regions. IR region is always
* enabled.
*/
- memory_region_init_iommu(&vtd_dev_as->iommu, OBJECT(s),
- &s->iommu_ops, "intel_iommu_dmar",
+ memory_region_init_iommu(&vtd_dev_as->iommu, sizeof(vtd_dev_as->iommu),
+ TYPE_INTEL_IOMMU_MEMORY_REGION, OBJECT(s),
+ "intel_iommu_dmar",
UINT64_MAX);
memory_region_init_alias(&vtd_dev_as->sys_alias, OBJECT(s),
"vtd_sys_alias", get_system_memory(),
@@ -2857,9 +2858,6 @@ static void vtd_init(IntelIOMMUState *s)
memset(s->w1cmask, 0, DMAR_REG_SIZE);
memset(s->womask, 0, DMAR_REG_SIZE);
- s->iommu_ops.translate = vtd_iommu_translate;
- s->iommu_ops.notify_flag_changed = vtd_iommu_notify_flag_changed;
- s->iommu_ops.replay = vtd_iommu_replay;
s->root = 0;
s->root_extended = false;
s->dmar_enabled = false;
@@ -3074,9 +3072,26 @@ static const TypeInfo vtd_info = {
.class_init = vtd_class_init,
};
+static void vtd_iommu_memory_region_class_init(ObjectClass *klass,
+ void *data)
+{
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+ imrc->translate = vtd_iommu_translate;
+ imrc->notify_flag_changed = vtd_iommu_notify_flag_changed;
+ imrc->replay = vtd_iommu_replay;
+}
+
+static const TypeInfo vtd_iommu_memory_region_info = {
+ .parent = TYPE_IOMMU_MEMORY_REGION,
+ .name = TYPE_INTEL_IOMMU_MEMORY_REGION,
+ .class_init = vtd_iommu_memory_region_class_init,
+};
+
static void vtd_register_types(void)
{
type_register_static(&vtd_info);
+ type_register_static(&vtd_iommu_memory_region_info);
}
type_init(vtd_register_types)
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 76a56ae..96e5d0b 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -133,6 +133,8 @@ typedef struct IOMMUState {
#define APB_DEVICE(obj) \
OBJECT_CHECK(APBState, (obj), TYPE_APB)
+#define TYPE_APB_IOMMU_MEMORY_REGION "pbm-iommu-memory-region"
+
typedef struct APBState {
PCIHostState parent_obj;
@@ -322,10 +324,6 @@ static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr,
return ret;
}
-static MemoryRegionIOMMUOps pbm_iommu_ops = {
- .translate = pbm_translate_iommu,
-};
-
static void iommu_config_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
@@ -697,7 +695,8 @@ PCIBus *pci_apb_init(hwaddr special_base,
is = &d->iommu;
memset(is, 0, sizeof(IOMMUState));
- memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops,
+ memory_region_init_iommu(&is->iommu, sizeof(is->iommu),
+ TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(dev),
"iommu-apb", UINT64_MAX);
address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as");
pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
@@ -860,11 +859,25 @@ static const TypeInfo pbm_pci_bridge_info = {
.class_init = pbm_pci_bridge_class_init,
};
+static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data)
+{
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+ imrc->translate = pbm_translate_iommu;
+}
+
+static const TypeInfo pbm_iommu_memory_region_info = {
+ .parent = TYPE_IOMMU_MEMORY_REGION,
+ .name = TYPE_APB_IOMMU_MEMORY_REGION,
+ .class_init = pbm_iommu_memory_region_class_init,
+};
+
static void pbm_register_types(void)
{
type_register_static(&pbm_host_info);
type_register_static(&pbm_pci_host_info);
type_register_static(&pbm_pci_bridge_info);
+ type_register_static(&pbm_iommu_memory_region_info);
}
type_init(pbm_register_types)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 6b6ced5..d07b4b4 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -248,12 +248,6 @@ static const VMStateDescription vmstate_spapr_tce_table = {
}
};
-static MemoryRegionIOMMUOps spapr_iommu_ops = {
- .translate = spapr_tce_translate_iommu,
- .get_min_page_size = spapr_tce_get_min_page_size,
- .notify_flag_changed = spapr_tce_notify_flag_changed,
-};
-
static int spapr_tce_table_realize(DeviceState *dev)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
@@ -266,7 +260,9 @@ static int spapr_tce_table_realize(DeviceState *dev)
memory_region_init(&tcet->root, tcetobj, tmp, UINT64_MAX);
snprintf(tmp, sizeof(tmp), "tce-iommu-%x", tcet->liobn);
- memory_region_init_iommu(&tcet->iommu, tcetobj, &spapr_iommu_ops, tmp, 0);
+ memory_region_init_iommu(&tcet->iommu, sizeof(tcet->iommu),
+ TYPE_SPAPR_IOMMU_MEMORY_REGION,
+ tcetobj, tmp, 0);
QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
@@ -639,9 +635,25 @@ static TypeInfo spapr_tce_table_info = {
.class_init = spapr_tce_table_class_init,
};
+static void spapr_iommu_memory_region_class_init(ObjectClass *klass, void *data)
+{
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+ imrc->translate = spapr_tce_translate_iommu;
+ imrc->get_min_page_size = spapr_tce_get_min_page_size;
+ imrc->notify_flag_changed = spapr_tce_notify_flag_changed;
+}
+
+static const TypeInfo spapr_iommu_memory_region_info = {
+ .parent = TYPE_IOMMU_MEMORY_REGION,
+ .name = TYPE_SPAPR_IOMMU_MEMORY_REGION,
+ .class_init = spapr_iommu_memory_region_class_init,
+};
+
static void register_types(void)
{
type_register_static(&spapr_tce_table_info);
+ type_register_static(&spapr_iommu_memory_region_info);
}
type_init(register_types);
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index e4fc82c..903b3ca 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -407,10 +407,6 @@ static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr,
return ret;
}
-static const MemoryRegionIOMMUOps s390_iommu_ops = {
- .translate = s390_translate_iommu,
-};
-
static S390PCIIOMMU *s390_pci_get_iommu(S390pciState *s, PCIBus *bus,
int devfn)
{
@@ -522,8 +518,9 @@ static const MemoryRegionOps s390_msi_ctrl_ops = {
void s390_pci_iommu_enable(S390PCIIOMMU *iommu)
{
char *name = g_strdup_printf("iommu-s390-%04x", iommu->pbdev->uid);
- memory_region_init_iommu(&iommu->iommu_mr, OBJECT(&iommu->mr),
- &s390_iommu_ops, name, iommu->pal + 1);
+ memory_region_init_iommu(&iommu->iommu_mr, sizeof(iommu->iommu_mr),
+ TYPE_S390_IOMMU_MEMORY_REGION, OBJECT(&iommu->mr),
+ name, iommu->pal + 1);
iommu->enabled = true;
memory_region_add_subregion(&iommu->mr, 0, MEMORY_REGION(&iommu->iommu_mr));
g_free(name);
@@ -1058,12 +1055,26 @@ static TypeInfo s390_pci_iommu_info = {
.instance_size = sizeof(S390PCIIOMMU),
};
+static void s390_iommu_memory_region_class_init(ObjectClass *klass, void *data)
+{
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+ imrc->translate = s390_translate_iommu;
+}
+
+static const TypeInfo s390_iommu_memory_region_info = {
+ .parent = TYPE_IOMMU_MEMORY_REGION,
+ .name = TYPE_S390_IOMMU_MEMORY_REGION,
+ .class_init = s390_iommu_memory_region_class_init,
+};
+
static void s390_pci_register_types(void)
{
type_register_static(&s390_pcihost_info);
type_register_static(&s390_pcibus_info);
type_register_static(&s390_pci_device_info);
type_register_static(&s390_pci_iommu_info);
+ type_register_static(&s390_iommu_memory_region_info);
}
type_init(s390_pci_register_types)
diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
index 6a599ed..67af2c1 100644
--- a/hw/s390x/s390-pci-bus.h
+++ b/hw/s390x/s390-pci-bus.h
@@ -24,6 +24,7 @@
#define TYPE_S390_PCI_BUS "s390-pcibus"
#define TYPE_S390_PCI_DEVICE "zpci"
#define TYPE_S390_PCI_IOMMU "s390-pci-iommu"
+#define TYPE_S390_IOMMU_MEMORY_REGION "s390-iommu-memory-region"
#define FH_MASK_ENABLE 0x80000000
#define FH_MASK_INSTANCE 0x7f000000
#define FH_MASK_SHM 0x00ff0000
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index a53c29c..b7beb8c 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -564,6 +564,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
hwaddr start, end;
IOMMUTLBEntry entry;
IOMMUMemoryRegion *iommu_mr;
+ IOMMUMemoryRegionClass *imrc;
cpu_synchronize_state(CPU(cpu));
@@ -623,8 +624,10 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
}
iommu_mr = &iommu->iommu_mr;
+ imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
+
while (start < end) {
- entry = iommu_mr->iommu_ops->translate(iommu_mr, start, IOMMU_NONE);
+ entry = imrc->translate(iommu_mr, start, IOMMU_NONE);
if (!entry.translated_addr) {
pbdev->state = ZPCI_FS_ERROR;
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 92980ab..b796601 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -25,6 +25,7 @@
#include "qemu/notify.h"
#include "qom/object.h"
#include "qemu/rcu.h"
+#include "hw/qdev-core.h"
#define RAM_ADDR_INVALID (~(ram_addr_t)0)
@@ -38,6 +39,12 @@
#define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region"
#define IOMMU_MEMORY_REGION(obj) \
OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_IOMMU_MEMORY_REGION)
+#define IOMMU_MEMORY_REGION_CLASS(klass) \
+ OBJECT_CLASS_CHECK(IOMMUMemoryRegionClass, (klass), \
+ TYPE_IOMMU_MEMORY_REGION)
+#define IOMMU_MEMORY_REGION_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(IOMMUMemoryRegionClass, (obj), \
+ TYPE_IOMMU_MEMORY_REGION)
typedef struct MemoryRegionOps MemoryRegionOps;
typedef struct MemoryRegionMmio MemoryRegionMmio;
@@ -193,9 +200,10 @@ struct MemoryRegionOps {
const MemoryRegionMmio old_mmio;
};
-typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps;
+typedef struct IOMMUMemoryRegionClass {
+ /* private */
+ struct DeviceClass parent_class;
-struct MemoryRegionIOMMUOps {
/*
* Return a TLB entry that contains a given address. Flag should
* be the access permission of this translation operation. We can
@@ -212,7 +220,7 @@ struct MemoryRegionIOMMUOps {
IOMMUNotifierFlag new_flags);
/* Set this up to provide customized IOMMU replay function */
void (*replay)(IOMMUMemoryRegion *iommu, IOMMUNotifier *notifier);
-};
+} IOMMUMemoryRegionClass;
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
@@ -261,7 +269,6 @@ struct MemoryRegion {
struct IOMMUMemoryRegion {
MemoryRegion parent_obj;
- const MemoryRegionIOMMUOps *iommu_ops;
QLIST_HEAD(, IOMMUNotifier) iommu_notify;
IOMMUNotifierFlag iommu_notify_flags;
};
@@ -622,21 +629,24 @@ static inline void memory_region_init_reservation(MemoryRegion *mr,
}
/**
- * memory_region_init_iommu: Initialize a memory region that translates
- * addresses
+ * memory_region_init_iommu: Initialize a memory region of a custom type
+ * that translates addresses
*
* An IOMMU region translates addresses and forwards accesses to a target
* memory region.
*
- * @iommu_mr: the #IOMMUMemoryRegion to be initialized
+ * @typename: QOM class name
+ * @_iommu_mr: the #IOMMUMemoryRegion to be initialized
+ * @instance_size: the IOMMUMemoryRegion subclass instance size
* @owner: the object that tracks the region's reference count
* @ops: a function that translates addresses into the @target region
* @name: used for debugging; not visible to the user or ABI
* @size: size of the region.
*/
-void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
- struct Object *owner,
- const MemoryRegionIOMMUOps *ops,
+void memory_region_init_iommu(void *_iommu_mr,
+ size_t instance_size,
+ const char *mrtypename,
+ Object *owner,
const char *name,
uint64_t size);
@@ -707,6 +717,21 @@ static inline IOMMUMemoryRegion *memory_region_get_iommu(MemoryRegion *mr)
return NULL;
}
+/**
+ * memory_region_get_iommu_class_nocheck: returns iommu memory region class
+ * if an iommu or NULL if not
+ *
+ * Returns pointer to IOMMUMemoryRegioniClass if a memory region is an iommu,
+ * otherwise NULL. This is fast path avoinding QOM checking, use with caution.
+ *
+ * @mr: the memory region being queried
+ */
+static inline IOMMUMemoryRegionClass *memory_region_get_iommu_class_nocheck(
+ IOMMUMemoryRegion *iommu_mr)
+{
+ return (IOMMUMemoryRegionClass *) (((Object *)iommu_mr)->class);
+}
+
#define memory_region_is_iommu(mr) (memory_region_get_iommu(mr) != NULL)
/**
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 45fba4f..08d8a26 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -32,6 +32,8 @@
#define INTEL_IOMMU_DEVICE(obj) \
OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
+#define TYPE_INTEL_IOMMU_MEMORY_REGION "intel-iommu-iommu-memory-region"
+
/* DMAR Hardware Unit Definition address (IOMMU unit) */
#define Q35_HOST_BRIDGE_IOMMU_ADDR 0xfed90000ULL
@@ -289,7 +291,6 @@ struct IntelIOMMUState {
uint32_t context_cache_gen; /* Should be in [1,MAX] */
GHashTable *iotlb; /* IOTLB */
- MemoryRegionIOMMUOps iommu_ops;
GHashTable *vtd_as_by_busptr; /* VTDBus objects indexed by PCIBus* reference */
VTDBus *vtd_as_by_bus_num[VTD_PCI_BUS_MAX]; /* VTDBus objects indexed by bus number */
/* list of registered notifiers */
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index b353dff..5f708ee 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -582,6 +582,10 @@ typedef struct sPAPRTCETable sPAPRTCETable;
#define SPAPR_TCE_TABLE(obj) \
OBJECT_CHECK(sPAPRTCETable, (obj), TYPE_SPAPR_TCE_TABLE)
+#define TYPE_SPAPR_IOMMU_MEMORY_REGION "spapr-iommu-memory-region"
+#define SPAPR_IOMMU_MEMORY_REGION(obj) \
+ OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_SPAPR_IOMMU_MEMORY_REGION)
+
struct sPAPRTCETable {
DeviceState parent;
uint32_t liobn;
diff --git a/memory.c b/memory.c
index 45e10e2..69f697c 100644
--- a/memory.c
+++ b/memory.c
@@ -1506,19 +1506,20 @@ void memory_region_init_rom_device(MemoryRegion *mr,
mr->ram_block = qemu_ram_alloc(size, mr, errp);
}
-void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
+void memory_region_init_iommu(void *_iommu_mr,
+ size_t instance_size,
+ const char *mrtypename,
Object *owner,
- const MemoryRegionIOMMUOps *ops,
const char *name,
uint64_t size)
{
+ struct IOMMUMemoryRegion *iommu_mr;
struct MemoryRegion *mr;
- object_initialize(iommu_mr, sizeof(*iommu_mr), TYPE_IOMMU_MEMORY_REGION);
- mr = MEMORY_REGION(iommu_mr);
+ object_initialize(_iommu_mr, instance_size, mrtypename);
+ mr = MEMORY_REGION(_iommu_mr);
memory_region_do_init(mr, owner, name, size);
iommu_mr = IOMMU_MEMORY_REGION(mr);
- iommu_mr->iommu_ops = ops,
mr->terminates = true; /* then re-forwards */
QLIST_INIT(&iommu_mr->iommu_notify);
iommu_mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
@@ -1620,16 +1621,16 @@ static void memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iommu_mr)
{
IOMMUNotifierFlag flags = IOMMU_NOTIFIER_NONE;
IOMMUNotifier *iommu_notifier;
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
flags |= iommu_notifier->notifier_flags;
}
- if (flags != iommu_mr->iommu_notify_flags &&
- iommu_mr->iommu_ops->notify_flag_changed) {
- iommu_mr->iommu_ops->notify_flag_changed(iommu_mr,
- iommu_mr->iommu_notify_flags,
- flags);
+ if (flags != iommu_mr->iommu_notify_flags && imrc->notify_flag_changed) {
+ imrc->notify_flag_changed(iommu_mr,
+ iommu_mr->iommu_notify_flags,
+ flags);
}
iommu_mr->iommu_notify_flags = flags;
@@ -1655,8 +1656,10 @@ void memory_region_register_iommu_notifier(MemoryRegion *mr,
uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr)
{
- if (iommu_mr->iommu_ops && iommu_mr->iommu_ops->get_min_page_size) {
- return iommu_mr->iommu_ops->get_min_page_size(iommu_mr);
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
+
+ if (imrc->get_min_page_size) {
+ return imrc->get_min_page_size(iommu_mr);
}
return TARGET_PAGE_SIZE;
}
@@ -1664,19 +1667,20 @@ uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr)
void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
{
MemoryRegion *mr = MEMORY_REGION(iommu_mr);
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
hwaddr addr, granularity;
IOMMUTLBEntry iotlb;
/* If the IOMMU has its own replay callback, override */
- if (iommu_mr->iommu_ops->replay) {
- iommu_mr->iommu_ops->replay(iommu_mr, n);
+ if (imrc->replay) {
+ imrc->replay(iommu_mr, n);
return;
}
granularity = memory_region_iommu_get_min_page_size(iommu_mr);
for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
- iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, IOMMU_NONE);
+ iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE);
if (iotlb.perm != IOMMU_NONE) {
n->notify(n, &iotlb);
}
@@ -2855,8 +2859,10 @@ static const TypeInfo memory_region_info = {
static const TypeInfo iommu_memory_region_info = {
.parent = TYPE_MEMORY_REGION,
.name = TYPE_IOMMU_MEMORY_REGION,
+ .class_size = sizeof(IOMMUMemoryRegionClass),
.instance_size = sizeof(IOMMUMemoryRegion),
.instance_init = iommu_memory_region_initfn,
+ .abstract = true,
};
static void memory_register_types(void)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 31/41] nbd: Create struct for tracking export info
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (29 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 30/41] memory/iommu: introduce IOMMUMemoryRegionClass Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 32/41] nbd: Don't bother tracing an NBD_OPT_ABORT response failure Paolo Bonzini
` (10 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel
From: Eric Blake <eblake@redhat.com>
The NBD Protocol is introducing some additional information
about exports, such as minimum request size and alignment, as
well as an advertised maximum request size. It will be easier
to feed this information back to the block layer if we gather
all the information into a struct, rather than adding yet more
pointer parameters during negotiation.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-2-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
block/nbd-client.c | 18 ++++++++----------
block/nbd-client.h | 3 +--
block/nbd.c | 2 +-
include/block/nbd.h | 15 +++++++++++----
nbd/client.c | 44 ++++++++++++++++++++++----------------------
qemu-nbd.c | 10 ++++------
6 files changed, 47 insertions(+), 45 deletions(-)
diff --git a/block/nbd-client.c b/block/nbd-client.c
index 208f907..aab1e32 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -242,7 +242,7 @@ int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset,
ssize_t ret;
if (flags & BDRV_REQ_FUA) {
- assert(client->nbdflags & NBD_FLAG_SEND_FUA);
+ assert(client->info.flags & NBD_FLAG_SEND_FUA);
request.flags |= NBD_CMD_FLAG_FUA;
}
@@ -270,12 +270,12 @@ int nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
};
NBDReply reply;
- if (!(client->nbdflags & NBD_FLAG_SEND_WRITE_ZEROES)) {
+ if (!(client->info.flags & NBD_FLAG_SEND_WRITE_ZEROES)) {
return -ENOTSUP;
}
if (flags & BDRV_REQ_FUA) {
- assert(client->nbdflags & NBD_FLAG_SEND_FUA);
+ assert(client->info.flags & NBD_FLAG_SEND_FUA);
request.flags |= NBD_CMD_FLAG_FUA;
}
if (!(flags & BDRV_REQ_MAY_UNMAP)) {
@@ -299,7 +299,7 @@ int nbd_client_co_flush(BlockDriverState *bs)
NBDReply reply;
ssize_t ret;
- if (!(client->nbdflags & NBD_FLAG_SEND_FLUSH)) {
+ if (!(client->info.flags & NBD_FLAG_SEND_FLUSH)) {
return 0;
}
@@ -327,7 +327,7 @@ int nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
NBDReply reply;
ssize_t ret;
- if (!(client->nbdflags & NBD_FLAG_SEND_TRIM)) {
+ if (!(client->info.flags & NBD_FLAG_SEND_TRIM)) {
return 0;
}
@@ -385,19 +385,17 @@ int nbd_client_init(BlockDriverState *bs,
qio_channel_set_blocking(QIO_CHANNEL(sioc), true, NULL);
ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), export,
- &client->nbdflags,
tlscreds, hostname,
- &client->ioc,
- &client->size, errp);
+ &client->ioc, &client->info, errp);
if (ret < 0) {
logout("Failed to negotiate with the NBD server\n");
return ret;
}
- if (client->nbdflags & NBD_FLAG_SEND_FUA) {
+ if (client->info.flags & NBD_FLAG_SEND_FUA) {
bs->supported_write_flags = BDRV_REQ_FUA;
bs->supported_zero_flags |= BDRV_REQ_FUA;
}
- if (client->nbdflags & NBD_FLAG_SEND_WRITE_ZEROES) {
+ if (client->info.flags & NBD_FLAG_SEND_WRITE_ZEROES) {
bs->supported_zero_flags |= BDRV_REQ_MAY_UNMAP;
}
diff --git a/block/nbd-client.h b/block/nbd-client.h
index 49636bc..df80771 100644
--- a/block/nbd-client.h
+++ b/block/nbd-client.h
@@ -20,8 +20,7 @@
typedef struct NBDClientSession {
QIOChannelSocket *sioc; /* The master data channel */
QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */
- uint16_t nbdflags;
- off_t size;
+ NBDExportInfo info;
CoMutex send_mutex;
CoQueue free_sema;
diff --git a/block/nbd.c b/block/nbd.c
index d529305..4a9048c 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -492,7 +492,7 @@ static int64_t nbd_getlength(BlockDriverState *bs)
{
BDRVNBDState *s = bs->opaque;
- return s->client.size;
+ return s->client.info.size;
}
static void nbd_detach_aio_context(BlockDriverState *bs)
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 6d75d5a..9092374 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -123,13 +123,20 @@ enum {
* aren't overflowing some other buffer. */
#define NBD_MAX_NAME_SIZE 256
+/* Details collected by NBD_OPT_EXPORT_NAME and NBD_OPT_GO */
+struct NBDExportInfo {
+ uint64_t size;
+ uint16_t flags;
+};
+typedef struct NBDExportInfo NBDExportInfo;
+
ssize_t nbd_rwv(QIOChannel *ioc, struct iovec *iov, size_t niov, size_t length,
bool do_read, Error **errp);
-int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
+int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
QCryptoTLSCreds *tlscreds, const char *hostname,
- QIOChannel **outioc,
- off_t *size, Error **errp);
-int nbd_init(int fd, QIOChannelSocket *sioc, uint16_t flags, off_t size,
+ QIOChannel **outioc, NBDExportInfo *info,
+ Error **errp);
+int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
Error **errp);
ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest *request);
ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp);
diff --git a/nbd/client.c b/nbd/client.c
index 9c52b9b..1250273 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -425,13 +425,13 @@ static QIOChannel *nbd_receive_starttls(QIOChannel *ioc,
}
-int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
+int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
QCryptoTLSCreds *tlscreds, const char *hostname,
- QIOChannel **outioc,
- off_t *size, Error **errp)
+ QIOChannel **outioc, NBDExportInfo *info,
+ Error **errp)
{
char buf[256];
- uint64_t magic, s;
+ uint64_t magic;
int rc;
bool zeroes = true;
@@ -532,17 +532,17 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
}
/* Read the response */
- if (nbd_read(ioc, &s, sizeof(s), errp) < 0) {
+ if (nbd_read(ioc, &info->size, sizeof(info->size), errp) < 0) {
error_prepend(errp, "Failed to read export length");
goto fail;
}
- *size = be64_to_cpu(s);
+ be64_to_cpus(&info->size);
- if (nbd_read(ioc, flags, sizeof(*flags), errp) < 0) {
+ if (nbd_read(ioc, &info->flags, sizeof(info->flags), errp) < 0) {
error_prepend(errp, "Failed to read export flags");
goto fail;
}
- be16_to_cpus(flags);
+ be16_to_cpus(&info->flags);
} else if (magic == NBD_CLIENT_MAGIC) {
uint32_t oldflags;
@@ -555,11 +555,11 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
goto fail;
}
- if (nbd_read(ioc, &s, sizeof(s), errp) < 0) {
+ if (nbd_read(ioc, &info->size, sizeof(info->size), errp) < 0) {
error_prepend(errp, "Failed to read export length");
goto fail;
}
- *size = be64_to_cpu(s);
+ be64_to_cpus(&info->size);
if (nbd_read(ioc, &oldflags, sizeof(oldflags), errp) < 0) {
error_prepend(errp, "Failed to read export flags");
@@ -570,13 +570,13 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
error_setg(errp, "Unexpected export flags %0x" PRIx32, oldflags);
goto fail;
}
- *flags = oldflags;
+ info->flags = oldflags;
} else {
error_setg(errp, "Bad magic received");
goto fail;
}
- trace_nbd_receive_negotiate_size_flags(*size, *flags);
+ trace_nbd_receive_negotiate_size_flags(info->size, info->flags);
if (zeroes && nbd_drop(ioc, 124, errp) < 0) {
error_prepend(errp, "Failed to read reserved block");
goto fail;
@@ -588,13 +588,13 @@ fail:
}
#ifdef __linux__
-int nbd_init(int fd, QIOChannelSocket *sioc, uint16_t flags, off_t size,
+int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
Error **errp)
{
- unsigned long sectors = size / BDRV_SECTOR_SIZE;
- if (size / BDRV_SECTOR_SIZE != sectors) {
- error_setg(errp, "Export size %lld too large for 32-bit kernel",
- (long long) size);
+ unsigned long sectors = info->size / BDRV_SECTOR_SIZE;
+ if (info->size / BDRV_SECTOR_SIZE != sectors) {
+ error_setg(errp, "Export size %" PRIu64 " too large for 32-bit kernel",
+ info->size);
return -E2BIG;
}
@@ -615,8 +615,8 @@ int nbd_init(int fd, QIOChannelSocket *sioc, uint16_t flags, off_t size,
}
trace_nbd_init_set_size(sectors);
- if (size % BDRV_SECTOR_SIZE) {
- trace_nbd_init_trailing_bytes(size % BDRV_SECTOR_SIZE);
+ if (info->size % BDRV_SECTOR_SIZE) {
+ trace_nbd_init_trailing_bytes(info->size % BDRV_SECTOR_SIZE);
}
if (ioctl(fd, NBD_SET_SIZE_BLOCKS, sectors) < 0) {
@@ -625,9 +625,9 @@ int nbd_init(int fd, QIOChannelSocket *sioc, uint16_t flags, off_t size,
return -serrno;
}
- if (ioctl(fd, NBD_SET_FLAGS, (unsigned long) flags) < 0) {
+ if (ioctl(fd, NBD_SET_FLAGS, (unsigned long) info->flags) < 0) {
if (errno == ENOTTY) {
- int read_only = (flags & NBD_FLAG_READ_ONLY) != 0;
+ int read_only = (info->flags & NBD_FLAG_READ_ONLY) != 0;
trace_nbd_init_set_readonly();
if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) {
@@ -685,7 +685,7 @@ int nbd_disconnect(int fd)
}
#else
-int nbd_init(int fd, QIOChannelSocket *ioc, uint16_t flags, off_t size,
+int nbd_init(int fd, QIOChannelSocket *ioc, NBDExportInfo *info,
Error **errp)
{
error_setg(errp, "nbd_init is only supported on Linux");
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 4dd3fd4..c8bd47f 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -255,8 +255,7 @@ static void *show_parts(void *arg)
static void *nbd_client_thread(void *arg)
{
char *device = arg;
- off_t size;
- uint16_t nbdflags;
+ NBDExportInfo info;
QIOChannelSocket *sioc;
int fd;
int ret;
@@ -271,9 +270,8 @@ static void *nbd_client_thread(void *arg)
goto out;
}
- ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), NULL, &nbdflags,
- NULL, NULL, NULL,
- &size, &local_error);
+ ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), NULL,
+ NULL, NULL, NULL, &info, &local_error);
if (ret < 0) {
if (local_error) {
error_report_err(local_error);
@@ -288,7 +286,7 @@ static void *nbd_client_thread(void *arg)
goto out_socket;
}
- ret = nbd_init(fd, sioc, nbdflags, size, &local_error);
+ ret = nbd_init(fd, sioc, &info, &local_error);
if (ret < 0) {
error_report_err(local_error);
goto out_fd;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 32/41] nbd: Don't bother tracing an NBD_OPT_ABORT response failure
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (30 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 31/41] nbd: Create struct for tracking export info Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 33/41] nbd: Expose and debug more NBD constants Paolo Bonzini
` (9 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel
From: Eric Blake <eblake@redhat.com>
We really don't care if our spec-compliant reply to NBD_OPT_ABORT
was received, so shave off some lines of code by not even tracing it.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-3-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
nbd/server.c | 15 ++++-----------
nbd/trace-events | 1 -
2 files changed, 4 insertions(+), 12 deletions(-)
diff --git a/nbd/server.c b/nbd/server.c
index 9b0c588..e15385b 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -376,7 +376,6 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
{
uint32_t flags;
bool fixedNewstyle = false;
- Error *local_err = NULL;
/* Client sends:
[ 0 .. 3] client flags
@@ -479,7 +478,9 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
if (ret < 0) {
return ret;
}
- /* Let the client keep trying, unless they asked to quit */
+ /* Let the client keep trying, unless they asked to
+ * quit. In this mode, we've already sent an error, so
+ * we can't ack the abort. */
if (option == NBD_OPT_ABORT) {
return 1;
}
@@ -498,15 +499,7 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
/* NBD spec says we must try to reply before
* disconnecting, but that we must also tolerate
* guests that don't wait for our reply. */
- nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, option,
- &local_err);
-
- if (local_err != NULL) {
- const char *error = error_get_pretty(local_err);
- trace_nbd_opt_abort_reply_failed(error);
- error_free(local_err);
- }
-
+ nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, option, NULL);
return 1;
case NBD_OPT_EXPORT_NAME:
diff --git a/nbd/trace-events b/nbd/trace-events
index 4b233b8..c6f898e 100644
--- a/nbd/trace-events
+++ b/nbd/trace-events
@@ -40,7 +40,6 @@ nbd_negotiate_options_newstyle(void) "Client supports fixed newstyle handshake"
nbd_negotiate_options_no_zeroes(void) "Client supports no zeroes at handshake end"
nbd_negotiate_options_check_magic(uint64_t magic) "Checking opts magic 0x%" PRIx64
nbd_negotiate_options_check_option(uint32_t option) "Checking option 0x%" PRIx32
-nbd_opt_abort_reply_failed(const char *error) "Reply to NBD_OPT_ABORT request failed: %s"
nbd_negotiate_begin(void) "Beginning negotiation"
nbd_negotiate_old_style(uint64_t size, unsigned flags) "advertising size %" PRIu64 " and flags %x"
nbd_negotiate_new_style_size_flags(uint64_t size, unsigned flags) "advertising size %" PRIu64 " and flags %x"
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 33/41] nbd: Expose and debug more NBD constants
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (31 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 32/41] nbd: Don't bother tracing an NBD_OPT_ABORT response failure Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 34/41] nbd: Simplify trace of client flags in negotiation Paolo Bonzini
` (8 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel
From: Eric Blake <eblake@redhat.com>
The NBD protocol has several constants defined in various extensions
that we are about to implement. Expose them to the code, along with
an easy way to map various constants to strings during diagnostic
messages.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-4-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
include/block/nbd.h | 37 +++++++++++++++------
nbd/client.c | 52 +++++++++++++++++++-----------
nbd/common.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++
nbd/nbd-internal.h | 10 +++---
nbd/server.c | 18 +++++++----
nbd/trace-events | 12 +++----
6 files changed, 175 insertions(+), 46 deletions(-)
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 9092374..4a22eca 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Red Hat, Inc.
+ * Copyright (C) 2016-2017 Red Hat, Inc.
* Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws>
*
* Network Block Device
@@ -83,18 +83,37 @@ typedef struct NBDReply NBDReply;
#define NBD_FLAG_C_FIXED_NEWSTYLE (1 << 0) /* Fixed newstyle protocol. */
#define NBD_FLAG_C_NO_ZEROES (1 << 1) /* End handshake without zeroes. */
-/* Reply types. */
+/* Option requests. */
+#define NBD_OPT_EXPORT_NAME (1)
+#define NBD_OPT_ABORT (2)
+#define NBD_OPT_LIST (3)
+/* #define NBD_OPT_PEEK_EXPORT (4) not in use */
+#define NBD_OPT_STARTTLS (5)
+#define NBD_OPT_INFO (6)
+#define NBD_OPT_GO (7)
+#define NBD_OPT_STRUCTURED_REPLY (8)
+
+/* Option reply types. */
#define NBD_REP_ERR(value) ((UINT32_C(1) << 31) | (value))
#define NBD_REP_ACK (1) /* Data sending finished. */
#define NBD_REP_SERVER (2) /* Export description. */
-
-#define NBD_REP_ERR_UNSUP NBD_REP_ERR(1) /* Unknown option */
-#define NBD_REP_ERR_POLICY NBD_REP_ERR(2) /* Server denied */
-#define NBD_REP_ERR_INVALID NBD_REP_ERR(3) /* Invalid length */
-#define NBD_REP_ERR_PLATFORM NBD_REP_ERR(4) /* Not compiled in */
-#define NBD_REP_ERR_TLS_REQD NBD_REP_ERR(5) /* TLS required */
-#define NBD_REP_ERR_SHUTDOWN NBD_REP_ERR(7) /* Server shutting down */
+#define NBD_REP_INFO (3) /* NBD_OPT_INFO/GO. */
+
+#define NBD_REP_ERR_UNSUP NBD_REP_ERR(1) /* Unknown option */
+#define NBD_REP_ERR_POLICY NBD_REP_ERR(2) /* Server denied */
+#define NBD_REP_ERR_INVALID NBD_REP_ERR(3) /* Invalid length */
+#define NBD_REP_ERR_PLATFORM NBD_REP_ERR(4) /* Not compiled in */
+#define NBD_REP_ERR_TLS_REQD NBD_REP_ERR(5) /* TLS required */
+#define NBD_REP_ERR_UNKNOWN NBD_REP_ERR(6) /* Export unknown */
+#define NBD_REP_ERR_SHUTDOWN NBD_REP_ERR(7) /* Server shutting down */
+#define NBD_REP_ERR_BLOCK_SIZE_REQD NBD_REP_ERR(8) /* Need INFO_BLOCK_SIZE */
+
+/* Info types, used during NBD_REP_INFO */
+#define NBD_INFO_EXPORT 0
+#define NBD_INFO_NAME 1
+#define NBD_INFO_DESCRIPTION 2
+#define NBD_INFO_BLOCK_SIZE 3
/* Request flags, sent from client to server during transmission phase */
#define NBD_CMD_FLAG_FUA (1 << 0) /* 'force unit access' during write */
diff --git a/nbd/client.c b/nbd/client.c
index 1250273..a443e51 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Red Hat, Inc.
+ * Copyright (C) 2016-2017 Red Hat, Inc.
* Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws>
*
* Network Block Device Client Side
@@ -104,7 +104,7 @@ static int nbd_send_option_request(QIOChannel *ioc, uint32_t opt,
if (len == -1) {
req.length = len = strlen(data);
}
- trace_nbd_send_option_request(opt, len);
+ trace_nbd_send_option_request(opt, nbd_opt_lookup(opt), len);
stq_be_p(&req.magic, NBD_OPTS_MAGIC);
stl_be_p(&req.option, opt);
@@ -154,7 +154,9 @@ static int nbd_receive_option_reply(QIOChannel *ioc, uint32_t opt,
be32_to_cpus(&reply->type);
be32_to_cpus(&reply->length);
- trace_nbd_receive_option_reply(reply->option, reply->type, reply->length);
+ trace_nbd_receive_option_reply(reply->option, nbd_opt_lookup(reply->option),
+ reply->type, nbd_rep_lookup(reply->type),
+ reply->length);
if (reply->magic != NBD_REP_MAGIC) {
error_setg(errp, "Unexpected option reply magic");
@@ -188,12 +190,16 @@ static int nbd_handle_reply_err(QIOChannel *ioc, nbd_opt_reply *reply,
if (reply->length) {
if (reply->length > NBD_MAX_BUFFER_SIZE) {
- error_setg(errp, "server's error message is too long");
+ error_setg(errp, "server error 0x%" PRIx32
+ " (%s) message is too long",
+ reply->type, nbd_rep_lookup(reply->type));
goto cleanup;
}
msg = g_malloc(reply->length + 1);
if (nbd_read(ioc, msg, reply->length, errp) < 0) {
- error_prepend(errp, "failed to read option error message");
+ error_prepend(errp, "failed to read option error 0x%" PRIx32
+ " (%s) message",
+ reply->type, nbd_rep_lookup(reply->type));
goto cleanup;
}
msg[reply->length] = '\0';
@@ -201,38 +207,48 @@ static int nbd_handle_reply_err(QIOChannel *ioc, nbd_opt_reply *reply,
switch (reply->type) {
case NBD_REP_ERR_UNSUP:
- trace_nbd_reply_err_unsup(reply->option);
+ trace_nbd_reply_err_unsup(reply->option, nbd_opt_lookup(reply->option));
result = 0;
goto cleanup;
case NBD_REP_ERR_POLICY:
- error_setg(errp, "Denied by server for option %" PRIx32,
- reply->option);
+ error_setg(errp, "Denied by server for option %" PRIx32 " (%s)",
+ reply->option, nbd_opt_lookup(reply->option));
break;
case NBD_REP_ERR_INVALID:
- error_setg(errp, "Invalid data length for option %" PRIx32,
- reply->option);
+ error_setg(errp, "Invalid data length for option %" PRIx32 " (%s)",
+ reply->option, nbd_opt_lookup(reply->option));
break;
case NBD_REP_ERR_PLATFORM:
- error_setg(errp, "Server lacks support for option %" PRIx32,
- reply->option);
+ error_setg(errp, "Server lacks support for option %" PRIx32 " (%s)",
+ reply->option, nbd_opt_lookup(reply->option));
break;
case NBD_REP_ERR_TLS_REQD:
- error_setg(errp, "TLS negotiation required before option %" PRIx32,
- reply->option);
+ error_setg(errp, "TLS negotiation required before option %" PRIx32
+ " (%s)", reply->option, nbd_opt_lookup(reply->option));
+ break;
+
+ case NBD_REP_ERR_UNKNOWN:
+ error_setg(errp, "Requested export not available for option %" PRIx32
+ " (%s)", reply->option, nbd_opt_lookup(reply->option));
break;
case NBD_REP_ERR_SHUTDOWN:
- error_setg(errp, "Server shutting down before option %" PRIx32,
- reply->option);
+ error_setg(errp, "Server shutting down before option %" PRIx32 " (%s)",
+ reply->option, nbd_opt_lookup(reply->option));
+ break;
+
+ case NBD_REP_ERR_BLOCK_SIZE_REQD:
+ error_setg(errp, "Server requires INFO_BLOCK_SIZE for option %" PRIx32
+ " (%s)", reply->option, nbd_opt_lookup(reply->option));
break;
default:
- error_setg(errp, "Unknown error code when asking for option %" PRIx32,
- reply->option);
+ error_setg(errp, "Unknown error code when asking for option %" PRIx32
+ " (%s)", reply->option, nbd_opt_lookup(reply->option));
break;
}
diff --git a/nbd/common.c b/nbd/common.c
index 4dab41e..a2f28f2 100644
--- a/nbd/common.c
+++ b/nbd/common.c
@@ -101,3 +101,95 @@ void nbd_tls_handshake(QIOTask *task,
data->complete = true;
g_main_loop_quit(data->loop);
}
+
+
+const char *nbd_opt_lookup(uint32_t opt)
+{
+ switch (opt) {
+ case NBD_OPT_EXPORT_NAME:
+ return "export name";
+ case NBD_OPT_ABORT:
+ return "abort";
+ case NBD_OPT_LIST:
+ return "list";
+ case NBD_OPT_STARTTLS:
+ return "starttls";
+ case NBD_OPT_INFO:
+ return "info";
+ case NBD_OPT_GO:
+ return "go";
+ case NBD_OPT_STRUCTURED_REPLY:
+ return "structured reply";
+ default:
+ return "<unknown>";
+ }
+}
+
+
+const char *nbd_rep_lookup(uint32_t rep)
+{
+ switch (rep) {
+ case NBD_REP_ACK:
+ return "ack";
+ case NBD_REP_SERVER:
+ return "server";
+ case NBD_REP_INFO:
+ return "info";
+ case NBD_REP_ERR_UNSUP:
+ return "unsupported";
+ case NBD_REP_ERR_POLICY:
+ return "denied by policy";
+ case NBD_REP_ERR_INVALID:
+ return "invalid";
+ case NBD_REP_ERR_PLATFORM:
+ return "platform lacks support";
+ case NBD_REP_ERR_TLS_REQD:
+ return "TLS required";
+ case NBD_REP_ERR_UNKNOWN:
+ return "export unknown";
+ case NBD_REP_ERR_SHUTDOWN:
+ return "server shutting down";
+ case NBD_REP_ERR_BLOCK_SIZE_REQD:
+ return "block size required";
+ default:
+ return "<unknown>";
+ }
+}
+
+
+const char *nbd_info_lookup(uint16_t info)
+{
+ switch (info) {
+ case NBD_INFO_EXPORT:
+ return "export";
+ case NBD_INFO_NAME:
+ return "name";
+ case NBD_INFO_DESCRIPTION:
+ return "description";
+ case NBD_INFO_BLOCK_SIZE:
+ return "block size";
+ default:
+ return "<unknown>";
+ }
+}
+
+
+const char *nbd_cmd_lookup(uint16_t cmd)
+{
+ switch (cmd) {
+ case NBD_CMD_READ:
+ return "read";
+ case NBD_CMD_WRITE:
+ return "write";
+ case NBD_CMD_DISC:
+ return "discard";
+ case NBD_CMD_FLUSH:
+ return "flush";
+ case NBD_CMD_TRIM:
+ return "trim";
+ case NBD_CMD_WRITE_ZEROES:
+ return "write zeroes";
+ default:
+ return "<unknown>";
+ }
+}
diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
index cf6ecbf..bf95601 100644
--- a/nbd/nbd-internal.h
+++ b/nbd/nbd-internal.h
@@ -57,12 +57,6 @@
#define NBD_SET_TIMEOUT _IO(0xab, 9)
#define NBD_SET_FLAGS _IO(0xab, 10)
-#define NBD_OPT_EXPORT_NAME (1)
-#define NBD_OPT_ABORT (2)
-#define NBD_OPT_LIST (3)
-#define NBD_OPT_PEEK_EXPORT (4)
-#define NBD_OPT_STARTTLS (5)
-
/* NBD errors are based on errno numbers, so there is a 1:1 mapping,
* but only a limited set of errno values is specified in the protocol.
* Everything else is squashed to EINVAL.
@@ -133,6 +127,10 @@ struct NBDTLSHandshakeData {
void nbd_tls_handshake(QIOTask *task,
void *opaque);
+const char *nbd_opt_lookup(uint32_t opt);
+const char *nbd_rep_lookup(uint32_t rep);
+const char *nbd_info_lookup(uint16_t info);
+const char *nbd_cmd_lookup(uint16_t info);
int nbd_drop(QIOChannel *ioc, size_t size, Error **errp);
diff --git a/nbd/server.c b/nbd/server.c
index e15385b..27a0aab 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Red Hat, Inc.
+ * Copyright (C) 2016-2017 Red Hat, Inc.
* Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws>
*
* Network Block Device Server Side
@@ -139,7 +139,8 @@ static int nbd_negotiate_send_rep_len(QIOChannel *ioc, uint32_t type,
{
uint64_t magic;
- trace_nbd_negotiate_send_rep_len(opt, type, len);
+ trace_nbd_negotiate_send_rep_len(opt, nbd_opt_lookup(opt),
+ type, nbd_rep_lookup(type), len);
magic = cpu_to_be64(NBD_REP_MAGIC);
if (nbd_write(ioc, &magic, sizeof(magic), errp) < 0) {
@@ -441,7 +442,8 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
}
length = be32_to_cpu(length);
- trace_nbd_negotiate_options_check_option(option);
+ trace_nbd_negotiate_options_check_option(option,
+ nbd_opt_lookup(option));
if (client->tlscreds &&
client->ioc == (QIOChannel *)client->sioc) {
QIOChannel *tioc;
@@ -532,8 +534,8 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
NBD_REP_ERR_UNSUP,
option, errp,
"Unsupported option 0x%"
- PRIx32,
- option);
+ PRIx32 " (%s)", option,
+ nbd_opt_lookup(option));
if (ret < 0) {
return ret;
}
@@ -549,7 +551,8 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
return nbd_negotiate_handle_export_name(client, length, errp);
default:
- error_setg(errp, "Unsupported option 0x%" PRIx32, option);
+ error_setg(errp, "Unsupported option 0x%" PRIx32 " (%s)",
+ option, nbd_opt_lookup(option));
return -EINVAL;
}
}
@@ -1033,7 +1036,8 @@ static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
return -EIO;
}
- trace_nbd_co_receive_request_decode_type(request->handle, request->type);
+ trace_nbd_co_receive_request_decode_type(request->handle, request->type,
+ nbd_cmd_lookup(request->type));
if (request->type != NBD_CMD_WRITE) {
/* No payload, we are ready to read the next request. */
diff --git a/nbd/trace-events b/nbd/trace-events
index c6f898e..5e2f961 100644
--- a/nbd/trace-events
+++ b/nbd/trace-events
@@ -1,8 +1,8 @@
# nbd/client.c
nbd_unknown_error(int err) "Squashing unexpected error %d to EINVAL"
-nbd_send_option_request(uint32_t opt, uint32_t len) "Sending option request %" PRIu32", len %" PRIu32
-nbd_receive_option_reply(uint32_t option, uint32_t type, uint32_t length) "Received option reply %" PRIx32", type %" PRIx32", len %" PRIu32
-nbd_reply_err_unsup(uint32_t option) "server doesn't understand request %" PRIx32 ", attempting fallback"
+nbd_send_option_request(uint32_t opt, const char *name, uint32_t len) "Sending option request %" PRIu32" (%s), len %" PRIu32
+nbd_receive_option_reply(uint32_t option, const char *optname, uint32_t type, const char *typename, uint32_t length) "Received option reply %" PRIx32" (%s), type %" PRIx32" (%s), len %" PRIu32
+nbd_reply_err_unsup(uint32_t option, const char *name) "server doesn't understand request %" PRIx32 " (%s), attempting fallback"
nbd_receive_query_exports_start(const char *wantname) "Querying export list for '%s'"
nbd_receive_query_exports_success(const char *wantname) "Found desired export name '%s'"
nbd_receive_starttls_request(void) "Requesting TLS from server"
@@ -28,7 +28,7 @@ nbd_send_request(uint64_t from, uint32_t len, uint64_t handle, uint16_t flags, u
nbd_receive_reply(uint32_t magic, int32_t error, uint64_t handle) "Got reply: { magic = 0x%" PRIx32 ", .error = % " PRId32 ", handle = %" PRIu64" }"
# nbd/server.c
-nbd_negotiate_send_rep_len(uint32_t opt, uint32_t type, uint32_t len) "Reply opt=%" PRIx32 " type=%" PRIx32 " len=%" PRIu32
+nbd_negotiate_send_rep_len(uint32_t opt, const char *optname, uint32_t type, const char *typename, uint32_t len) "Reply opt=%" PRIx32 " (%s), type=%" PRIx32 " (%s), len=%" PRIu32
nbd_negotiate_send_rep_err(const char *msg) "sending error message \"%s\""
nbd_negotiate_send_rep_list(const char *name, const char *desc) "Advertising export name '%s' description '%s'"
nbd_negotiate_handle_export_name(void) "Checking length"
@@ -39,7 +39,7 @@ nbd_negotiate_options_flags(void) "Checking client flags"
nbd_negotiate_options_newstyle(void) "Client supports fixed newstyle handshake"
nbd_negotiate_options_no_zeroes(void) "Client supports no zeroes at handshake end"
nbd_negotiate_options_check_magic(uint64_t magic) "Checking opts magic 0x%" PRIx64
-nbd_negotiate_options_check_option(uint32_t option) "Checking option 0x%" PRIx32
+nbd_negotiate_options_check_option(uint32_t option, const char *name) "Checking option 0x%" PRIx32 " (%s)"
nbd_negotiate_begin(void) "Beginning negotiation"
nbd_negotiate_old_style(uint64_t size, unsigned flags) "advertising size %" PRIu64 " and flags %x"
nbd_negotiate_new_style_size_flags(uint64_t size, unsigned flags) "advertising size %" PRIu64 " and flags %x"
@@ -49,7 +49,7 @@ nbd_send_reply(int32_t error, uint64_t handle) "Sending response to client: { .e
nbd_blk_aio_attached(const char *name, void *ctx) "Export %s: Attaching clients to AIO context %p\n"
nbd_blk_aio_detach(const char *name, void *ctx) "Export %s: Detaching clients from AIO context %p\n"
nbd_co_send_reply(uint64_t handle, uint32_t error, int len) "Send reply: handle = %" PRIu64 ", error = %" PRIu32 ", len = %d"
-nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type) "Decoding type: handle = %" PRIu64 ", type = %" PRIu16
+nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const char *name) "Decoding type: handle = %" PRIu64 ", type = %" PRIu16 " (%s)"
nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Payload received: handle = %" PRIu64 ", len = %" PRIu32
nbd_co_receive_request_cmd_write(uint32_t len) "Reading %" PRIu32 " byte(s)"
nbd_trip(void) "Reading request"
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 34/41] nbd: Simplify trace of client flags in negotiation
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (32 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 33/41] nbd: Expose and debug more NBD constants Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 35/41] nbd: Refactor reply to NBD_OPT_EXPORT_NAME Paolo Bonzini
` (7 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel
From: Eric Blake <eblake@redhat.com>
Simplify the tracing of client flags in the server, and return -EINVAL
instead of -EIO if we successfully read but don't like those flags.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-5-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
nbd/server.c | 6 ++----
nbd/trace-events | 4 +---
2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/nbd/server.c b/nbd/server.c
index 27a0aab..8e363d3 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -396,21 +396,19 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
error_prepend(errp, "read failed: ");
return -EIO;
}
- trace_nbd_negotiate_options_flags();
be32_to_cpus(&flags);
+ trace_nbd_negotiate_options_flags(flags);
if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {
- trace_nbd_negotiate_options_newstyle();
fixedNewstyle = true;
flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;
}
if (flags & NBD_FLAG_C_NO_ZEROES) {
- trace_nbd_negotiate_options_no_zeroes();
client->no_zeroes = true;
flags &= ~NBD_FLAG_C_NO_ZEROES;
}
if (flags != 0) {
error_setg(errp, "Unknown client flags 0x%" PRIx32 " received", flags);
- return -EIO;
+ return -EINVAL;
}
while (1) {
diff --git a/nbd/trace-events b/nbd/trace-events
index 5e2f961..8db0500 100644
--- a/nbd/trace-events
+++ b/nbd/trace-events
@@ -35,9 +35,7 @@ nbd_negotiate_handle_export_name(void) "Checking length"
nbd_negotiate_handle_export_name_request(const char *name) "Client requested export '%s'"
nbd_negotiate_handle_starttls(void) "Setting up TLS"
nbd_negotiate_handle_starttls_handshake(void) "Starting TLS handshake"
-nbd_negotiate_options_flags(void) "Checking client flags"
-nbd_negotiate_options_newstyle(void) "Client supports fixed newstyle handshake"
-nbd_negotiate_options_no_zeroes(void) "Client supports no zeroes at handshake end"
+nbd_negotiate_options_flags(uint32_t flags) "Received client flags 0x%" PRIx32
nbd_negotiate_options_check_magic(uint64_t magic) "Checking opts magic 0x%" PRIx64
nbd_negotiate_options_check_option(uint32_t option, const char *name) "Checking option 0x%" PRIx32 " (%s)"
nbd_negotiate_begin(void) "Beginning negotiation"
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 35/41] nbd: Refactor reply to NBD_OPT_EXPORT_NAME
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (33 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 34/41] nbd: Simplify trace of client flags in negotiation Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 36/41] nbd: Implement NBD_OPT_GO on server Paolo Bonzini
` (6 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel
From: Eric Blake <eblake@redhat.com>
Reply directly in nbd_negotiate_handle_export_name(), rather than
waiting until nbd_negotiate_options() completes. This will make it
easier to implement NBD_OPT_GO. Pass additional parameters around,
rather than stashing things inside NBDClient.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-6-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
nbd/server.c | 50 ++++++++++++++++++++++++++++----------------------
1 file changed, 28 insertions(+), 22 deletions(-)
diff --git a/nbd/server.c b/nbd/server.c
index 8e363d3..841986d 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -84,7 +84,6 @@ struct NBDClient {
int refcount;
void (*close_fn)(NBDClient *client, bool negotiated);
- bool no_zeroes;
NBDExport *exp;
QCryptoTLSCreds *tlscreds;
char *tlsaclname;
@@ -277,9 +276,13 @@ static int nbd_negotiate_handle_list(NBDClient *client, uint32_t length,
}
static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length,
+ uint16_t myflags, bool no_zeroes,
Error **errp)
{
char name[NBD_MAX_NAME_SIZE + 1];
+ char buf[8 + 4 + 124] = "";
+ size_t len;
+ int ret;
/* Client sends:
[20 .. xx] export name (length bytes)
@@ -303,6 +306,17 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length,
return -EINVAL;
}
+ trace_nbd_negotiate_new_style_size_flags(client->exp->size,
+ client->exp->nbdflags | myflags);
+ stq_be_p(buf, client->exp->size);
+ stw_be_p(buf + 8, client->exp->nbdflags | myflags);
+ len = no_zeroes ? 10 : sizeof(buf);
+ ret = nbd_write(client->ioc, buf, len, errp);
+ if (ret < 0) {
+ error_prepend(errp, "write failed: ");
+ return ret;
+ }
+
QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
nbd_export_get(client->exp);
@@ -373,14 +387,17 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
* 1 if client sent NBD_OPT_ABORT, i.e. on valid disconnect,
* errp is not set
*/
-static int nbd_negotiate_options(NBDClient *client, Error **errp)
+static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
+ Error **errp)
{
uint32_t flags;
bool fixedNewstyle = false;
+ bool no_zeroes = false;
/* Client sends:
[ 0 .. 3] client flags
+ Then we loop until NBD_OPT_EXPORT_NAME:
[ 0 .. 7] NBD_OPTS_MAGIC
[ 8 .. 11] NBD option
[12 .. 15] Data length
@@ -403,7 +420,7 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;
}
if (flags & NBD_FLAG_C_NO_ZEROES) {
- client->no_zeroes = true;
+ no_zeroes = true;
flags &= ~NBD_FLAG_C_NO_ZEROES;
}
if (flags != 0) {
@@ -503,7 +520,9 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
return 1;
case NBD_OPT_EXPORT_NAME:
- return nbd_negotiate_handle_export_name(client, length, errp);
+ return nbd_negotiate_handle_export_name(client, length,
+ myflags, no_zeroes,
+ errp);
case NBD_OPT_STARTTLS:
if (nbd_drop(client->ioc, length, errp) < 0) {
@@ -546,7 +565,9 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
*/
switch (option) {
case NBD_OPT_EXPORT_NAME:
- return nbd_negotiate_handle_export_name(client, length, errp);
+ return nbd_negotiate_handle_export_name(client, length,
+ myflags, no_zeroes,
+ errp);
default:
error_setg(errp, "Unsupported option 0x%" PRIx32 " (%s)",
@@ -572,7 +593,6 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA |
NBD_FLAG_SEND_WRITE_ZEROES);
bool oldStyle;
- size_t len;
/* Old style negotiation header without options
[ 0 .. 7] passwd ("NBDMAGIC")
@@ -586,10 +606,7 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
[ 0 .. 7] passwd ("NBDMAGIC")
[ 8 .. 15] magic (NBD_OPTS_MAGIC)
[16 .. 17] server flags (0)
- ....options sent....
- [18 .. 25] size
- [26 .. 27] export flags
- [28 .. 151] reserved (0, omit if no_zeroes)
+ ....options sent, ending in NBD_OPT_EXPORT_NAME....
*/
qio_channel_set_blocking(client->ioc, false, NULL);
@@ -618,24 +635,13 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
error_prepend(errp, "write failed: ");
return -EINVAL;
}
- ret = nbd_negotiate_options(client, errp);
+ ret = nbd_negotiate_options(client, myflags, errp);
if (ret != 0) {
if (ret < 0) {
error_prepend(errp, "option negotiation failed: ");
}
return ret;
}
-
- trace_nbd_negotiate_new_style_size_flags(
- client->exp->size, client->exp->nbdflags | myflags);
- stq_be_p(buf + 18, client->exp->size);
- stw_be_p(buf + 26, client->exp->nbdflags | myflags);
- len = client->no_zeroes ? 10 : sizeof(buf) - 18;
- ret = nbd_write(client->ioc, buf + 18, len, errp);
- if (ret < 0) {
- error_prepend(errp, "write failed: ");
- return ret;
- }
}
trace_nbd_negotiate_success();
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 36/41] nbd: Implement NBD_OPT_GO on server
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (34 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 35/41] nbd: Refactor reply to NBD_OPT_EXPORT_NAME Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 37/41] nbd: Implement NBD_OPT_GO on client Paolo Bonzini
` (5 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel
From: Eric Blake <eblake@redhat.com>
NBD_OPT_EXPORT_NAME is lousy: per the NBD protocol, any failure
requires us to close the connection rather than report an error.
Therefore, upstream NBD recently added NBD_OPT_GO as the improved
version of the option that does what we want [1], along with
NBD_OPT_INFO that returns the same information but does not
transition to transmission phase.
[1] https://github.com/NetworkBlockDevice/nbd/blob/extension-info/doc/proto.md
This is a first cut at the information types, and only passes the
same information already available through NBD_OPT_LIST and
NBD_OPT_EXPORT_NAME; items like NBD_INFO_BLOCK_SIZE (and thus any
use of NBD_REP_ERR_BLOCK_SIZE_REQD) are intentionally left for
later patches.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-7-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
nbd/server.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
nbd/trace-events | 3 +
2 files changed, 179 insertions(+), 3 deletions(-)
diff --git a/nbd/server.c b/nbd/server.c
index 841986d..e84d012 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -141,6 +141,7 @@ static int nbd_negotiate_send_rep_len(QIOChannel *ioc, uint32_t type,
trace_nbd_negotiate_send_rep_len(opt, nbd_opt_lookup(opt),
type, nbd_rep_lookup(type), len);
+ assert(len < NBD_MAX_BUFFER_SIZE);
magic = cpu_to_be64(NBD_REP_MAGIC);
if (nbd_write(ioc, &magic, sizeof(magic), errp) < 0) {
error_prepend(errp, "write failed (rep magic): ");
@@ -275,6 +276,8 @@ static int nbd_negotiate_handle_list(NBDClient *client, uint32_t length,
return nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, NBD_OPT_LIST, errp);
}
+/* Send a reply to NBD_OPT_EXPORT_NAME.
+ * Return -errno on error, 0 on success. */
static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length,
uint16_t myflags, bool no_zeroes,
Error **errp)
@@ -323,6 +326,162 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length,
return 0;
}
+/* Send a single NBD_REP_INFO, with a buffer @buf of @length bytes.
+ * The buffer does NOT include the info type prefix.
+ * Return -errno on error, 0 if ready to send more. */
+static int nbd_negotiate_send_info(NBDClient *client, uint32_t opt,
+ uint16_t info, uint32_t length, void *buf,
+ Error **errp)
+{
+ int rc;
+
+ trace_nbd_negotiate_send_info(info, nbd_info_lookup(info), length);
+ rc = nbd_negotiate_send_rep_len(client->ioc, NBD_REP_INFO, opt,
+ sizeof(info) + length, errp);
+ if (rc < 0) {
+ return rc;
+ }
+ cpu_to_be16s(&info);
+ if (nbd_write(client->ioc, &info, sizeof(info), errp) < 0) {
+ return -EIO;
+ }
+ if (nbd_write(client->ioc, buf, length, errp) < 0) {
+ return -EIO;
+ }
+ return 0;
+}
+
+/* Handle NBD_OPT_INFO and NBD_OPT_GO.
+ * Return -errno on error, 0 if ready for next option, and 1 to move
+ * into transmission phase. */
+static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
+ uint32_t opt, uint16_t myflags,
+ Error **errp)
+{
+ int rc;
+ char name[NBD_MAX_NAME_SIZE + 1];
+ NBDExport *exp;
+ uint16_t requests;
+ uint16_t request;
+ uint32_t namelen;
+ bool sendname = false;
+ char buf[sizeof(uint64_t) + sizeof(uint16_t)];
+ const char *msg;
+
+ /* Client sends:
+ 4 bytes: L, name length (can be 0)
+ L bytes: export name
+ 2 bytes: N, number of requests (can be 0)
+ N * 2 bytes: N requests
+ */
+ if (length < sizeof(namelen) + sizeof(requests)) {
+ msg = "overall request too short";
+ goto invalid;
+ }
+ if (nbd_read(client->ioc, &namelen, sizeof(namelen), errp) < 0) {
+ return -EIO;
+ }
+ be32_to_cpus(&namelen);
+ length -= sizeof(namelen);
+ if (namelen > length - sizeof(requests) || (length - namelen) % 2) {
+ msg = "name length is incorrect";
+ goto invalid;
+ }
+ if (nbd_read(client->ioc, name, namelen, errp) < 0) {
+ return -EIO;
+ }
+ name[namelen] = '\0';
+ length -= namelen;
+ trace_nbd_negotiate_handle_export_name_request(name);
+
+ if (nbd_read(client->ioc, &requests, sizeof(requests), errp) < 0) {
+ return -EIO;
+ }
+ be16_to_cpus(&requests);
+ length -= sizeof(requests);
+ trace_nbd_negotiate_handle_info_requests(requests);
+ if (requests != length / sizeof(request)) {
+ msg = "incorrect number of requests for overall length";
+ goto invalid;
+ }
+ while (requests--) {
+ if (nbd_read(client->ioc, &request, sizeof(request), errp) < 0) {
+ return -EIO;
+ }
+ be16_to_cpus(&request);
+ length -= sizeof(request);
+ trace_nbd_negotiate_handle_info_request(request,
+ nbd_info_lookup(request));
+ /* For now, we only care about NBD_INFO_NAME; everything else
+ * is either a request we don't know or something we send
+ * regardless of request. */
+ if (request == NBD_INFO_NAME) {
+ sendname = true;
+ }
+ }
+
+ exp = nbd_export_find(name);
+ if (!exp) {
+ return nbd_negotiate_send_rep_err(client->ioc, NBD_REP_ERR_UNKNOWN,
+ opt, errp, "export '%s' not present",
+ name);
+ }
+
+ /* Don't bother sending NBD_INFO_NAME unless client requested it */
+ if (sendname) {
+ rc = nbd_negotiate_send_info(client, opt, NBD_INFO_NAME, length, name,
+ errp);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+
+ /* Send NBD_INFO_DESCRIPTION only if available, regardless of
+ * client request */
+ if (exp->description) {
+ size_t len = strlen(exp->description);
+
+ rc = nbd_negotiate_send_info(client, opt, NBD_INFO_DESCRIPTION,
+ len, exp->description, errp);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+
+ /* Send NBD_INFO_EXPORT always */
+ trace_nbd_negotiate_new_style_size_flags(exp->size,
+ exp->nbdflags | myflags);
+ stq_be_p(buf, exp->size);
+ stw_be_p(buf + 8, exp->nbdflags | myflags);
+ rc = nbd_negotiate_send_info(client, opt, NBD_INFO_EXPORT,
+ sizeof(buf), buf, errp);
+ if (rc < 0) {
+ return rc;
+ }
+
+ /* Final reply */
+ rc = nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, opt, errp);
+ if (rc < 0) {
+ return rc;
+ }
+
+ if (opt == NBD_OPT_GO) {
+ client->exp = exp;
+ QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
+ nbd_export_get(client->exp);
+ rc = 1;
+ }
+ return rc;
+
+ invalid:
+ if (nbd_drop(client->ioc, length, errp) < 0) {
+ return -EIO;
+ }
+ return nbd_negotiate_send_rep_err(client->ioc, NBD_REP_ERR_INVALID, opt,
+ errp, "%s", msg);
+}
+
+
/* Handle NBD_OPT_STARTTLS. Return NULL to drop connection, or else the
* new channel for all further (now-encrypted) communication. */
static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
@@ -380,7 +539,8 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
}
/* nbd_negotiate_options
- * Process all NBD_OPT_* client option commands.
+ * Process all NBD_OPT_* client option commands, during fixed newstyle
+ * negotiation.
* Return:
* -errno on error, errp is set
* 0 on successful negotiation, errp is not set
@@ -397,7 +557,7 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
/* Client sends:
[ 0 .. 3] client flags
- Then we loop until NBD_OPT_EXPORT_NAME:
+ Then we loop until NBD_OPT_EXPORT_NAME or NBD_OPT_GO:
[ 0 .. 7] NBD_OPTS_MAGIC
[ 8 .. 11] NBD option
[12 .. 15] Data length
@@ -524,6 +684,19 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
myflags, no_zeroes,
errp);
+ case NBD_OPT_INFO:
+ case NBD_OPT_GO:
+ ret = nbd_negotiate_handle_info(client, length, option,
+ myflags, errp);
+ if (ret == 1) {
+ assert(option == NBD_OPT_GO);
+ return 0;
+ }
+ if (ret) {
+ return ret;
+ }
+ break;
+
case NBD_OPT_STARTTLS:
if (nbd_drop(client->ioc, length, errp) < 0) {
return -EIO;
@@ -606,7 +779,7 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
[ 0 .. 7] passwd ("NBDMAGIC")
[ 8 .. 15] magic (NBD_OPTS_MAGIC)
[16 .. 17] server flags (0)
- ....options sent, ending in NBD_OPT_EXPORT_NAME....
+ ....options sent, ending in NBD_OPT_EXPORT_NAME or NBD_OPT_GO....
*/
qio_channel_set_blocking(client->ioc, false, NULL);
diff --git a/nbd/trace-events b/nbd/trace-events
index 8db0500..5230c61 100644
--- a/nbd/trace-events
+++ b/nbd/trace-events
@@ -33,6 +33,9 @@ nbd_negotiate_send_rep_err(const char *msg) "sending error message \"%s\""
nbd_negotiate_send_rep_list(const char *name, const char *desc) "Advertising export name '%s' description '%s'"
nbd_negotiate_handle_export_name(void) "Checking length"
nbd_negotiate_handle_export_name_request(const char *name) "Client requested export '%s'"
+nbd_negotiate_send_info(int info, const char *name, uint32_t length) "Sending NBD_REP_INFO type %d (%s) with remaining length %" PRIu32
+nbd_negotiate_handle_info_requests(int requests) "Client requested %d items of info"
+nbd_negotiate_handle_info_request(int request, const char *name) "Client requested info %d (%s)"
nbd_negotiate_handle_starttls(void) "Setting up TLS"
nbd_negotiate_handle_starttls_handshake(void) "Starting TLS handshake"
nbd_negotiate_options_flags(uint32_t flags) "Received client flags 0x%" PRIx32
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 37/41] nbd: Implement NBD_OPT_GO on client
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (35 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 36/41] nbd: Implement NBD_OPT_GO on server Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 38/41] nbd: Implement NBD_INFO_BLOCK_SIZE on server Paolo Bonzini
` (4 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel
From: Eric Blake <eblake@redhat.com>
NBD_OPT_EXPORT_NAME is lousy: per the NBD protocol, any failure
requires the server to close the connection rather than report an
error to us. Therefore, upstream NBD recently added NBD_OPT_GO as
the improved version of the option that does what we want [1]: it
reports sane errors on failures, and on success provides at least
as much info as NBD_OPT_EXPORT_NAME.
[1] https://github.com/NetworkBlockDevice/nbd/blob/extension-info/doc/proto.md
This is a first cut at use of the information types. Note that we
do not need to use NBD_OPT_INFO, and that use of NBD_OPT_GO means
we no longer have to use NBD_OPT_LIST to learn whether a server
requires TLS (this requires servers that gracefully handle unknown
NBD_OPT, many servers prior to qemu 2.5 were buggy, but I have patched
qemu, upstream nbd, and nbdkit in the meantime, in part because of
interoperability testing with this patch). We still fall back to
NBD_OPT_LIST when NBD_OPT_GO is not supported on the server, as it
is still one last chance for a nicer error message. Later patches
will use further info, like NBD_INFO_BLOCK_SIZE.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-8-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
nbd/client.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
nbd/nbd-internal.h | 3 ++
nbd/trace-events | 3 ++
3 files changed, 130 insertions(+), 2 deletions(-)
diff --git a/nbd/client.c b/nbd/client.c
index a443e51..1e98ca9 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -350,6 +350,114 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
}
+/* Returns -1 if NBD_OPT_GO proves the export @wantname cannot be
+ * used, 0 if NBD_OPT_GO is unsupported (fall back to NBD_OPT_LIST and
+ * NBD_OPT_EXPORT_NAME in that case), and > 0 if the export is good to
+ * go (with @info populated). */
+static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
+ NBDExportInfo *info, Error **errp)
+{
+ nbd_opt_reply reply;
+ uint32_t len = strlen(wantname);
+ uint16_t type;
+ int error;
+ char *buf;
+
+ /* The protocol requires that the server send NBD_INFO_EXPORT with
+ * a non-zero flags (at least NBD_FLAG_HAS_FLAGS must be set); so
+ * flags still 0 is a witness of a broken server. */
+ info->flags = 0;
+
+ trace_nbd_opt_go_start(wantname);
+ buf = g_malloc(4 + len + 2 + 1);
+ stl_be_p(buf, len);
+ memcpy(buf + 4, wantname, len);
+ /* No requests, live with whatever server sends */
+ stw_be_p(buf + 4 + len, 0);
+ if (nbd_send_option_request(ioc, NBD_OPT_GO, len + 6, buf, errp) < 0) {
+ return -1;
+ }
+
+ while (1) {
+ if (nbd_receive_option_reply(ioc, NBD_OPT_GO, &reply, errp) < 0) {
+ return -1;
+ }
+ error = nbd_handle_reply_err(ioc, &reply, errp);
+ if (error <= 0) {
+ return error;
+ }
+ len = reply.length;
+
+ if (reply.type == NBD_REP_ACK) {
+ /* Server is done sending info and moved into transmission
+ phase, but make sure it sent flags */
+ if (len) {
+ error_setg(errp, "server sent invalid NBD_REP_ACK");
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ if (!info->flags) {
+ error_setg(errp, "broken server omitted NBD_INFO_EXPORT");
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ trace_nbd_opt_go_success();
+ return 1;
+ }
+ if (reply.type != NBD_REP_INFO) {
+ error_setg(errp, "unexpected reply type %" PRIx32 ", expected %x",
+ reply.type, NBD_REP_INFO);
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ if (len < sizeof(type)) {
+ error_setg(errp, "NBD_REP_INFO length %" PRIu32 " is too short",
+ len);
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ if (nbd_read(ioc, &type, sizeof(type), errp) < 0) {
+ error_prepend(errp, "failed to read info type");
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ len -= sizeof(type);
+ be16_to_cpus(&type);
+ switch (type) {
+ case NBD_INFO_EXPORT:
+ if (len != sizeof(info->size) + sizeof(info->flags)) {
+ error_setg(errp, "remaining export info len %" PRIu32
+ " is unexpected size", len);
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ if (nbd_read(ioc, &info->size, sizeof(info->size), errp) < 0) {
+ error_prepend(errp, "failed to read info size");
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ be64_to_cpus(&info->size);
+ if (nbd_read(ioc, &info->flags, sizeof(info->flags), errp) < 0) {
+ error_prepend(errp, "failed to read info flags");
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ be16_to_cpus(&info->flags);
+ trace_nbd_receive_negotiate_size_flags(info->size, info->flags);
+ break;
+
+ default:
+ trace_nbd_opt_go_info_unknown(type, nbd_info_lookup(type));
+ if (nbd_drop(ioc, len, errp) < 0) {
+ error_prepend(errp, "Failed to read info payload");
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ break;
+ }
+ }
+}
+
/* Return -1 on failure, 0 if wantname is an available export. */
static int nbd_receive_query_exports(QIOChannel *ioc,
const char *wantname,
@@ -531,11 +639,25 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
name = "";
}
if (fixedNewStyle) {
+ int result;
+
+ /* Try NBD_OPT_GO first - if it works, we are done (it
+ * also gives us a good message if the server requires
+ * TLS). If it is not available, fall back to
+ * NBD_OPT_LIST for nicer error messages about a missing
+ * export, then use NBD_OPT_EXPORT_NAME. */
+ result = nbd_opt_go(ioc, name, info, errp);
+ if (result < 0) {
+ goto fail;
+ }
+ if (result > 0) {
+ return 0;
+ }
/* Check our desired export is present in the
* server export list. Since NBD_OPT_EXPORT_NAME
* cannot return an error message, running this
- * query gives us good error reporting if the
- * server required TLS
+ * query gives us better error reporting if the
+ * export name is not available.
*/
if (nbd_receive_query_exports(ioc, name, errp) < 0) {
goto fail;
diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
index bf95601..4065bc6 100644
--- a/nbd/nbd-internal.h
+++ b/nbd/nbd-internal.h
@@ -37,8 +37,11 @@
* https://github.com/yoe/nbd/blob/master/doc/proto.md
*/
+/* Size of all NBD_OPT_*, without payload */
#define NBD_REQUEST_SIZE (4 + 2 + 2 + 8 + 8 + 4)
+/* Size of all NBD_REP_* sent in answer to most NBD_OPT_*, without payload */
#define NBD_REPLY_SIZE (4 + 4 + 8)
+
#define NBD_REQUEST_MAGIC 0x25609513
#define NBD_REPLY_MAGIC 0x67446698
#define NBD_OPTS_MAGIC 0x49484156454F5054LL
diff --git a/nbd/trace-events b/nbd/trace-events
index 5230c61..bd09fab 100644
--- a/nbd/trace-events
+++ b/nbd/trace-events
@@ -3,6 +3,9 @@ nbd_unknown_error(int err) "Squashing unexpected error %d to EINVAL"
nbd_send_option_request(uint32_t opt, const char *name, uint32_t len) "Sending option request %" PRIu32" (%s), len %" PRIu32
nbd_receive_option_reply(uint32_t option, const char *optname, uint32_t type, const char *typename, uint32_t length) "Received option reply %" PRIx32" (%s), type %" PRIx32" (%s), len %" PRIu32
nbd_reply_err_unsup(uint32_t option, const char *name) "server doesn't understand request %" PRIx32 " (%s), attempting fallback"
+nbd_opt_go_start(const char *name) "Attempting NBD_OPT_GO for export '%s'"
+nbd_opt_go_success(void) "Export is good to go"
+nbd_opt_go_info_unknown(int info, const char *name) "Ignoring unknown info %d (%s)"
nbd_receive_query_exports_start(const char *wantname) "Querying export list for '%s'"
nbd_receive_query_exports_success(const char *wantname) "Found desired export name '%s'"
nbd_receive_starttls_request(void) "Requesting TLS from server"
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 38/41] nbd: Implement NBD_INFO_BLOCK_SIZE on server
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (36 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 37/41] nbd: Implement NBD_OPT_GO on client Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 39/41] nbd: Implement NBD_INFO_BLOCK_SIZE on client Paolo Bonzini
` (3 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel
From: Eric Blake <eblake@redhat.com>
The upstream NBD Protocol has defined a new extension to allow
the server to advertise block sizes to the client, as well as
a way for the client to inform the server that it intends to
obey block sizes.
Thanks to a recent fix (commit df7b97ff), our real minimum
transfer size is always 1 (the block layer takes care of
read-modify-write on our behalf), but we're still more efficient
if we advertise 512 when the client supports it, as follows:
- OPT_INFO, but no NBD_INFO_BLOCK_SIZE: advertise 512, then
fail with NBD_REP_ERR_BLOCK_SIZE_REQD; client is free to try
something else since we don't disconnect
- OPT_INFO with NBD_INFO_BLOCK_SIZE: advertise 512
- OPT_GO, but no NBD_INFO_BLOCK_SIZE: advertise 1
- OPT_GO with NBD_INFO_BLOCK_SIZE: advertise 512
We can also advertise the optimum block size (presumably the
cluster size, when exporting a qcow2 file), and our absolute
maximum transfer size of 32M, to help newer clients avoid
EINVAL failures or abrupt disconnects on oversize requests.
We do not reject clients for using the older NBD_OPT_EXPORT_NAME;
we are no worse off for those clients than we used to be.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-9-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
nbd/server.c | 48 ++++++++++++++++++++++++++++++++++++++++++++----
nbd/trace-events | 1 +
2 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/nbd/server.c b/nbd/server.c
index e84d012..49ed574 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -365,6 +365,8 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
uint16_t request;
uint32_t namelen;
bool sendname = false;
+ bool blocksize = false;
+ uint32_t sizes[3];
char buf[sizeof(uint64_t) + sizeof(uint16_t)];
const char *msg;
@@ -412,11 +414,16 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
length -= sizeof(request);
trace_nbd_negotiate_handle_info_request(request,
nbd_info_lookup(request));
- /* For now, we only care about NBD_INFO_NAME; everything else
- * is either a request we don't know or something we send
- * regardless of request. */
- if (request == NBD_INFO_NAME) {
+ /* We care about NBD_INFO_NAME and NBD_INFO_BLOCK_SIZE;
+ * everything else is either a request we don't know or
+ * something we send regardless of request */
+ switch (request) {
+ case NBD_INFO_NAME:
sendname = true;
+ break;
+ case NBD_INFO_BLOCK_SIZE:
+ blocksize = true;
+ break;
}
}
@@ -448,6 +455,27 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
}
}
+ /* Send NBD_INFO_BLOCK_SIZE always, but tweak the minimum size
+ * according to whether the client requested it, and according to
+ * whether this is OPT_INFO or OPT_GO. */
+ /* minimum - 1 for back-compat, or 512 if client is new enough.
+ * TODO: consult blk_bs(blk)->bl.request_alignment? */
+ sizes[0] = (opt == NBD_OPT_INFO || blocksize) ? BDRV_SECTOR_SIZE : 1;
+ /* preferred - Hard-code to 4096 for now.
+ * TODO: is blk_bs(blk)->bl.opt_transfer appropriate? */
+ sizes[1] = 4096;
+ /* maximum - At most 32M, but smaller as appropriate. */
+ sizes[2] = MIN(blk_get_max_transfer(exp->blk), NBD_MAX_BUFFER_SIZE);
+ trace_nbd_negotiate_handle_info_block_size(sizes[0], sizes[1], sizes[2]);
+ cpu_to_be32s(&sizes[0]);
+ cpu_to_be32s(&sizes[1]);
+ cpu_to_be32s(&sizes[2]);
+ rc = nbd_negotiate_send_info(client, opt, NBD_INFO_BLOCK_SIZE,
+ sizeof(sizes), sizes, errp);
+ if (rc < 0) {
+ return rc;
+ }
+
/* Send NBD_INFO_EXPORT always */
trace_nbd_negotiate_new_style_size_flags(exp->size,
exp->nbdflags | myflags);
@@ -459,6 +487,18 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
return rc;
}
+ /* If the client is just asking for NBD_OPT_INFO, but forgot to
+ * request block sizes, return an error.
+ * TODO: consult blk_bs(blk)->request_align, and only error if it
+ * is not 1? */
+ if (opt == NBD_OPT_INFO && !blocksize) {
+ return nbd_negotiate_send_rep_err(client->ioc,
+ NBD_REP_ERR_BLOCK_SIZE_REQD, opt,
+ errp,
+ "request NBD_INFO_BLOCK_SIZE to "
+ "use this export");
+ }
+
/* Final reply */
rc = nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, opt, errp);
if (rc < 0) {
diff --git a/nbd/trace-events b/nbd/trace-events
index bd09fab..be3dce7 100644
--- a/nbd/trace-events
+++ b/nbd/trace-events
@@ -39,6 +39,7 @@ nbd_negotiate_handle_export_name_request(const char *name) "Client requested exp
nbd_negotiate_send_info(int info, const char *name, uint32_t length) "Sending NBD_REP_INFO type %d (%s) with remaining length %" PRIu32
nbd_negotiate_handle_info_requests(int requests) "Client requested %d items of info"
nbd_negotiate_handle_info_request(int request, const char *name) "Client requested info %d (%s)"
+nbd_negotiate_handle_info_block_size(uint32_t minimum, uint32_t preferred, uint32_t maximum) "advertising minimum 0x%" PRIx32 ", preferred 0x%" PRIx32 ", maximum 0x%" PRIx32
nbd_negotiate_handle_starttls(void) "Setting up TLS"
nbd_negotiate_handle_starttls_handshake(void) "Starting TLS handshake"
nbd_negotiate_options_flags(uint32_t flags) "Received client flags 0x%" PRIx32
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 39/41] nbd: Implement NBD_INFO_BLOCK_SIZE on client
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (37 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 38/41] nbd: Implement NBD_INFO_BLOCK_SIZE on server Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 40/41] vl: fix breakage of -tb-size Paolo Bonzini
` (2 subsequent siblings)
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel
From: Eric Blake <eblake@redhat.com>
The upstream NBD Protocol has defined a new extension to allow
the server to advertise block sizes to the client, as well as
a way for the client to inform the server whether it intends to
obey block sizes.
When using the block layer as the client, we will obey block
sizes; but when used as 'qemu-nbd -c' to hand off to the
kernel nbd module as the client, we are still waiting for the
kernel to implement a way for us to learn if it will honor
block sizes (perhaps by an addition to sysfs, rather than an
ioctl), as well as any way to tell the kernel what additional
block sizes to obey (NBD_SET_BLKSIZE appears to be accurate
for the minimum size, but preferred and maximum sizes would
probably be new ioctl()s), so until then, we need to make our
request for block sizes conditional.
When using ioctl(NBD_SET_BLKSIZE) to hand off to the kernel,
use the minimum block size as the sector size if it is larger
than 512, which also has the nice effect of cooperating with
(non-qemu) servers that don't do read-modify-write when
exposing a block device with 4k sectors; it might also allow
us to visit a file larger than 2T on a 32-bit kernel.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-10-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
block/nbd-client.c | 4 +++
block/nbd.c | 14 +++++++--
include/block/nbd.h | 6 ++++
nbd/client.c | 81 +++++++++++++++++++++++++++++++++++++++++++++--------
nbd/trace-events | 1 +
qemu-nbd.c | 2 +-
6 files changed, 92 insertions(+), 16 deletions(-)
diff --git a/block/nbd-client.c b/block/nbd-client.c
index aab1e32..25dd284 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -384,6 +384,7 @@ int nbd_client_init(BlockDriverState *bs,
logout("session init %s\n", export);
qio_channel_set_blocking(QIO_CHANNEL(sioc), true, NULL);
+ client->info.request_sizes = true;
ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), export,
tlscreds, hostname,
&client->ioc, &client->info, errp);
@@ -398,6 +399,9 @@ int nbd_client_init(BlockDriverState *bs,
if (client->info.flags & NBD_FLAG_SEND_WRITE_ZEROES) {
bs->supported_zero_flags |= BDRV_REQ_MAY_UNMAP;
}
+ if (client->info.min_block > bs->bl.request_alignment) {
+ bs->bl.request_alignment = client->info.min_block;
+ }
qemu_co_mutex_init(&client->send_mutex);
qemu_co_queue_init(&client->free_sema);
diff --git a/block/nbd.c b/block/nbd.c
index 4a9048c..a50d24b 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -472,9 +472,17 @@ static int nbd_co_flush(BlockDriverState *bs)
static void nbd_refresh_limits(BlockDriverState *bs, Error **errp)
{
- bs->bl.max_pdiscard = NBD_MAX_BUFFER_SIZE;
- bs->bl.max_pwrite_zeroes = NBD_MAX_BUFFER_SIZE;
- bs->bl.max_transfer = NBD_MAX_BUFFER_SIZE;
+ NBDClientSession *s = nbd_get_client_session(bs);
+ uint32_t max = MIN_NON_ZERO(NBD_MAX_BUFFER_SIZE, s->info.max_block);
+
+ bs->bl.max_pdiscard = max;
+ bs->bl.max_pwrite_zeroes = max;
+ bs->bl.max_transfer = max;
+
+ if (s->info.opt_block &&
+ s->info.opt_block > bs->bl.opt_transfer) {
+ bs->bl.opt_transfer = s->info.opt_block;
+ }
}
static void nbd_close(BlockDriverState *bs)
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 4a22eca..9c3d0a5 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -144,8 +144,14 @@ enum {
/* Details collected by NBD_OPT_EXPORT_NAME and NBD_OPT_GO */
struct NBDExportInfo {
+ /* Set by client before nbd_receive_negotiate() */
+ bool request_sizes;
+ /* Set by server results during nbd_receive_negotiate() */
uint64_t size;
uint16_t flags;
+ uint32_t min_block;
+ uint32_t opt_block;
+ uint32_t max_block;
};
typedef struct NBDExportInfo NBDExportInfo;
diff --git a/nbd/client.c b/nbd/client.c
index 1e98ca9..c3ee9f3 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -369,12 +369,17 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
info->flags = 0;
trace_nbd_opt_go_start(wantname);
- buf = g_malloc(4 + len + 2 + 1);
+ buf = g_malloc(4 + len + 2 + 2 * info->request_sizes + 1);
stl_be_p(buf, len);
memcpy(buf + 4, wantname, len);
- /* No requests, live with whatever server sends */
- stw_be_p(buf + 4 + len, 0);
- if (nbd_send_option_request(ioc, NBD_OPT_GO, len + 6, buf, errp) < 0) {
+ /* At most one request, everything else up to server */
+ stw_be_p(buf + 4 + len, info->request_sizes);
+ if (info->request_sizes) {
+ stw_be_p(buf + 4 + len + 2, NBD_INFO_BLOCK_SIZE);
+ }
+ if (nbd_send_option_request(ioc, NBD_OPT_GO,
+ 4 + len + 2 + 2 * info->request_sizes, buf,
+ errp) < 0) {
return -1;
}
@@ -405,8 +410,9 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
return 1;
}
if (reply.type != NBD_REP_INFO) {
- error_setg(errp, "unexpected reply type %" PRIx32 ", expected %x",
- reply.type, NBD_REP_INFO);
+ error_setg(errp, "unexpected reply type %" PRIx32
+ " (%s), expected %x",
+ reply.type, nbd_rep_lookup(reply.type), NBD_REP_INFO);
nbd_send_opt_abort(ioc);
return -1;
}
@@ -446,6 +452,51 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
trace_nbd_receive_negotiate_size_flags(info->size, info->flags);
break;
+ case NBD_INFO_BLOCK_SIZE:
+ if (len != sizeof(info->min_block) * 3) {
+ error_setg(errp, "remaining export info len %" PRIu32
+ " is unexpected size", len);
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ if (nbd_read(ioc, &info->min_block, sizeof(info->min_block),
+ errp) < 0) {
+ error_prepend(errp, "failed to read info minimum block size");
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ be32_to_cpus(&info->min_block);
+ if (!is_power_of_2(info->min_block)) {
+ error_setg(errp, "server minimum block size %" PRId32
+ "is not a power of two", info->min_block);
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ if (nbd_read(ioc, &info->opt_block, sizeof(info->opt_block),
+ errp) < 0) {
+ error_prepend(errp, "failed to read info preferred block size");
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ be32_to_cpus(&info->opt_block);
+ if (!is_power_of_2(info->opt_block) ||
+ info->opt_block < info->min_block) {
+ error_setg(errp, "server preferred block size %" PRId32
+ "is not valid", info->opt_block);
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ if (nbd_read(ioc, &info->max_block, sizeof(info->max_block),
+ errp) < 0) {
+ error_prepend(errp, "failed to read info maximum block size");
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ be32_to_cpus(&info->max_block);
+ trace_nbd_opt_go_info_block_size(info->min_block, info->opt_block,
+ info->max_block);
+ break;
+
default:
trace_nbd_opt_go_info_unknown(type, nbd_info_lookup(type));
if (nbd_drop(ioc, len, errp) < 0) {
@@ -729,8 +780,14 @@ fail:
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
Error **errp)
{
- unsigned long sectors = info->size / BDRV_SECTOR_SIZE;
- if (info->size / BDRV_SECTOR_SIZE != sectors) {
+ unsigned long sector_size = MAX(BDRV_SECTOR_SIZE, info->min_block);
+ unsigned long sectors = info->size / sector_size;
+
+ /* FIXME: Once the kernel module is patched to honor block sizes,
+ * and to advertise that fact to user space, we should update the
+ * hand-off to the kernel to use any block sizes we learned. */
+ assert(!info->request_sizes);
+ if (info->size / sector_size != sectors) {
error_setg(errp, "Export size %" PRIu64 " too large for 32-bit kernel",
info->size);
return -E2BIG;
@@ -744,17 +801,17 @@ int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
return -serrno;
}
- trace_nbd_init_set_block_size(BDRV_SECTOR_SIZE);
+ trace_nbd_init_set_block_size(sector_size);
- if (ioctl(fd, NBD_SET_BLKSIZE, (unsigned long)BDRV_SECTOR_SIZE) < 0) {
+ if (ioctl(fd, NBD_SET_BLKSIZE, sector_size) < 0) {
int serrno = errno;
error_setg(errp, "Failed setting NBD block size");
return -serrno;
}
trace_nbd_init_set_size(sectors);
- if (info->size % BDRV_SECTOR_SIZE) {
- trace_nbd_init_trailing_bytes(info->size % BDRV_SECTOR_SIZE);
+ if (info->size % sector_size) {
+ trace_nbd_init_trailing_bytes(info->size % sector_size);
}
if (ioctl(fd, NBD_SET_SIZE_BLOCKS, sectors) < 0) {
diff --git a/nbd/trace-events b/nbd/trace-events
index be3dce7..f5024d8 100644
--- a/nbd/trace-events
+++ b/nbd/trace-events
@@ -6,6 +6,7 @@ nbd_reply_err_unsup(uint32_t option, const char *name) "server doesn't understan
nbd_opt_go_start(const char *name) "Attempting NBD_OPT_GO for export '%s'"
nbd_opt_go_success(void) "Export is good to go"
nbd_opt_go_info_unknown(int info, const char *name) "Ignoring unknown info %d (%s)"
+nbd_opt_go_info_block_size(uint32_t minimum, uint32_t preferred, uint32_t maximum) "Block sizes are 0x%" PRIx32 ", 0x%" PRIx32 ", 0x%" PRIx32
nbd_receive_query_exports_start(const char *wantname) "Querying export list for '%s'"
nbd_receive_query_exports_success(const char *wantname) "Found desired export name '%s'"
nbd_receive_starttls_request(void) "Requesting TLS from server"
diff --git a/qemu-nbd.c b/qemu-nbd.c
index c8bd47f..78d05be 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -255,7 +255,7 @@ static void *show_parts(void *arg)
static void *nbd_client_thread(void *arg)
{
char *device = arg;
- NBDExportInfo info;
+ NBDExportInfo info = { .request_sizes = false, };
QIOChannelSocket *sioc;
int fd;
int ret;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 40/41] vl: fix breakage of -tb-size
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (38 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 39/41] nbd: Implement NBD_INFO_BLOCK_SIZE on client Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 41/41] translate-all: remove redundant !tcg_enabled check in dump_exec_info Paolo Bonzini
2017-07-13 16:05 ` [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze no-reply
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Emilio G. Cota
From: "Emilio G. Cota" <cota@braap.org>
Commit e7b161d573 ("vl: add tcg_enabled() for tcg related code") adds
a check to exit the program when !tcg_enabled() while parsing the -tb-size
flag.
It turns out that when the -tb-size flag is evaluated, tcg_enabled() can
only return 0, since it is set (or not) much later by configure_accelerator().
Fix it by unconditionally exiting if the flag is passed to a QEMU binary
built with !CONFIG_TCG.
Signed-off-by: Emilio G. Cota <cota@braap.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
vl.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/vl.c b/vl.c
index f7560de..85cdbbf 100644
--- a/vl.c
+++ b/vl.c
@@ -3933,10 +3933,10 @@ int main(int argc, char **argv, char **envp)
configure_rtc(opts);
break;
case QEMU_OPTION_tb_size:
- if (!tcg_enabled()) {
- error_report("TCG is disabled");
- exit(1);
- }
+#ifndef CONFIG_TCG
+ error_report("TCG is disabled");
+ exit(1);
+#endif
if (qemu_strtoul(optarg, NULL, 0, &tcg_tb_size) < 0) {
error_report("Invalid argument to -tb-size");
exit(1);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PULL 41/41] translate-all: remove redundant !tcg_enabled check in dump_exec_info
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (39 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 40/41] vl: fix breakage of -tb-size Paolo Bonzini
@ 2017-07-13 14:24 ` Paolo Bonzini
2017-07-13 16:05 ` [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze no-reply
41 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Emilio G. Cota
From: "Emilio G. Cota" <cota@braap.org>
This check is redundant because it is already performed by the only
caller of dump_exec_info -- the caller was updated by b7da97eef
("monitor: Check whether TCG is enabled before running the "info jit"
code").
Checking twice wouldn't necessarily be too bad, but here the check also
returns with tb_lock held. So we can either do the check before tb_lock is
acquired, or just get rid of it. Given that it is redundant, I am going
for the latter option.
Signed-off-by: Emilio G. Cota <cota@braap.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
accel/tcg/translate-all.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 0caf80d..4e1831c 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1851,11 +1851,6 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
tb_lock();
- if (!tcg_enabled()) {
- cpu_fprintf(f, "TCG not enabled\n");
- return;
- }
-
target_code_size = 0;
max_target_code_size = 0;
cross_page = 0;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PULL 23/41] mttcg/i386: Patch instruction using async_safe_* framework
2017-07-13 14:24 ` [Qemu-devel] [PULL 23/41] mttcg/i386: Patch instruction using async_safe_* framework Paolo Bonzini
@ 2017-07-13 15:16 ` Alex Bennée
2017-07-14 8:24 ` Thomas Huth
0 siblings, 1 reply; 46+ messages in thread
From: Alex Bennée @ 2017-07-13 15:16 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel, Peter Maydell, Pranith Kumar
Paolo Bonzini <pbonzini@redhat.com> writes:
> From: Pranith Kumar <bobby.prani@gmail.com>
>
> In mttcg, calling pause_all_vcpus() during execution from the
> generated TBs causes a deadlock if some vCPU is waiting for exclusive
> execution in start_exclusive(). Fix this by using the aync_safe_*
> framework instead of pausing vcpus for patching instructions.
>
> CC: Paolo Bonzini <pbonzini@redhat.com>
> CC: Peter Maydell <peter.maydell@linaro.org>
> Reviewed-by: Richard Henderson <rth@twiddle.net>
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Looks like some UTF-8 mangling has occurred somewhere here.
> Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
> Message-Id: <20170712215143.19594-2-bobby.prani@gmail.com>
> [Get rid completely of the TCG-specific code. - Paolo]
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> hw/i386/kvmvapic.c | 85 +++++++++++++++++++++++++-----------------------------
> 1 file changed, 39 insertions(+), 46 deletions(-)
>
> diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
> index 0d9ef77..fc962c5 100644
> --- a/hw/i386/kvmvapic.c
> +++ b/hw/i386/kvmvapic.c
> @@ -383,8 +383,7 @@ static void patch_byte(X86CPU *cpu, target_ulong addr, uint8_t byte)
> cpu_memory_rw_debug(CPU(cpu), addr, &byte, 1, 1);
> }
>
> -static void patch_call(VAPICROMState *s, X86CPU *cpu, target_ulong ip,
> - uint32_t target)
> +static void patch_call(X86CPU *cpu, target_ulong ip, uint32_t target)
> {
> uint32_t offset;
>
> @@ -393,77 +392,71 @@ static void patch_call(VAPICROMState *s, X86CPU *cpu, target_ulong ip,
> cpu_memory_rw_debug(CPU(cpu), ip + 1, (void *)&offset, sizeof(offset), 1);
> }
>
> -static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
> +typedef struct PatchInfo {
> + VAPICHandlers *handler;
> + target_ulong ip;
> +} PatchInfo;
> +
> +static void do_patch_instruction(CPUState *cs, run_on_cpu_data data)
> {
> - CPUState *cs = CPU(cpu);
> - CPUX86State *env = &cpu->env;
> - VAPICHandlers *handlers;
> + X86CPU *x86_cpu = X86_CPU(cs);
> + PatchInfo *info = (PatchInfo *) data.host_ptr;
> + VAPICHandlers *handlers = info->handler;
> + target_ulong ip = info->ip;
> uint8_t opcode[2];
> uint32_t imm32 = 0;
> - target_ulong current_pc = 0;
> - target_ulong current_cs_base = 0;
> - uint32_t current_flags = 0;
> -
> - if (smp_cpus == 1) {
> - handlers = &s->rom_state.up;
> - } else {
> - handlers = &s->rom_state.mp;
> - }
> -
> - if (tcg_enabled()) {
> - cpu_restore_state(cs, cs->mem_io_pc);
> - cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base,
> - ¤t_flags);
> - /* Account this instruction, because we will exit the tb.
> - This is the first instruction in the block. Therefore
> - there is no need in restoring CPU state. */
> - if (use_icount) {
> - --cs->icount_decr.u16.low;
> - }
> - }
> -
> - pause_all_vcpus();
>
> cpu_memory_rw_debug(cs, ip, opcode, sizeof(opcode), 0);
>
> switch (opcode[0]) {
> case 0x89: /* mov r32 to r/m32 */
> - patch_byte(cpu, ip, 0x50 + modrm_reg(opcode[1])); /* push reg */
> - patch_call(s, cpu, ip + 1, handlers->set_tpr);
> + patch_byte(x86_cpu, ip, 0x50 + modrm_reg(opcode[1])); /* push reg */
> + patch_call(x86_cpu, ip + 1, handlers->set_tpr);
> break;
> case 0x8b: /* mov r/m32 to r32 */
> - patch_byte(cpu, ip, 0x90);
> - patch_call(s, cpu, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
> + patch_byte(x86_cpu, ip, 0x90);
> + patch_call(x86_cpu, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
> break;
> case 0xa1: /* mov abs to eax */
> - patch_call(s, cpu, ip, handlers->get_tpr[0]);
> + patch_call(x86_cpu, ip, handlers->get_tpr[0]);
> break;
> case 0xa3: /* mov eax to abs */
> - patch_call(s, cpu, ip, handlers->set_tpr_eax);
> + patch_call(x86_cpu, ip, handlers->set_tpr_eax);
> break;
> case 0xc7: /* mov imm32, r/m32 (c7/0) */
> - patch_byte(cpu, ip, 0x68); /* push imm32 */
> + patch_byte(x86_cpu, ip, 0x68); /* push imm32 */
> cpu_memory_rw_debug(cs, ip + 6, (void *)&imm32, sizeof(imm32), 0);
> cpu_memory_rw_debug(cs, ip + 1, (void *)&imm32, sizeof(imm32), 1);
> - patch_call(s, cpu, ip + 5, handlers->set_tpr);
> + patch_call(x86_cpu, ip + 5, handlers->set_tpr);
> break;
> case 0xff: /* push r/m32 */
> - patch_byte(cpu, ip, 0x50); /* push eax */
> - patch_call(s, cpu, ip + 1, handlers->get_tpr_stack);
> + patch_byte(x86_cpu, ip, 0x50); /* push eax */
> + patch_call(x86_cpu, ip + 1, handlers->get_tpr_stack);
> break;
> default:
> abort();
> }
>
> - resume_all_vcpus();
> + g_free(info);
> +}
> +
> +static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
> +{
> + CPUState *cs = CPU(cpu);
> + VAPICHandlers *handlers;
> + PatchInfo *info;
>
> - if (tcg_enabled()) {
> - /* Both tb_lock and iothread_mutex will be reset when
> - * longjmps back into the cpu_exec loop. */
> - tb_lock();
> - tb_gen_code(cs, current_pc, current_cs_base, current_flags, 1);
> - cpu_loop_exit_noexc(cs);
> + if (smp_cpus == 1) {
> + handlers = &s->rom_state.up;
> + } else {
> + handlers = &s->rom_state.mp;
> }
> +
> + info = g_new(PatchInfo, 1);
> + info->handler = handlers;
> + info->ip = ip;
> +
> + async_safe_run_on_cpu(cs, do_patch_instruction, RUN_ON_CPU_HOST_PTR(info));
> }
>
> void vapic_report_tpr_access(DeviceState *dev, CPUState *cs, target_ulong ip,
--
Alex Bennée
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
` (40 preceding siblings ...)
2017-07-13 14:24 ` [Qemu-devel] [PULL 41/41] translate-all: remove redundant !tcg_enabled check in dump_exec_info Paolo Bonzini
@ 2017-07-13 16:05 ` no-reply
2017-07-13 17:01 ` Paolo Bonzini
41 siblings, 1 reply; 46+ messages in thread
From: no-reply @ 2017-07-13 16:05 UTC (permalink / raw)
To: pbonzini; +Cc: famz, qemu-devel
Hi,
This series seems to have some coding style problems. See output below for
more information:
Type: series
Message-id: 1499955874-10954-1-git-send-email-pbonzini@redhat.com
Subject: [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze
=== TEST SCRIPT BEGIN ===
#!/bin/bash
BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0
git config --local diff.renamelimit 0
git config --local diff.renames True
commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done
exit $failed
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
- [tag update] patchew/1499955697-28045-1-git-send-email-peter.maydell@linaro.org -> patchew/1499955697-28045-1-git-send-email-peter.maydell@linaro.org
* [new tag] patchew/1499955874-10954-1-git-send-email-pbonzini@redhat.com -> patchew/1499955874-10954-1-git-send-email-pbonzini@redhat.com
* [new tag] patchew/1499958932-23839-1-git-send-email-peter.maydell@linaro.org -> patchew/1499958932-23839-1-git-send-email-peter.maydell@linaro.org
- [tag update] patchew/20170713110237.6712-1-lprosek@redhat.com -> patchew/20170713110237.6712-1-lprosek@redhat.com
* [new tag] patchew/20170713144352.2212-1-berrange@redhat.com -> patchew/20170713144352.2212-1-berrange@redhat.com
* [new tag] patchew/20170713153028.31065-1-el13635@mail.ntua.gr -> patchew/20170713153028.31065-1-el13635@mail.ntua.gr
Switched to a new branch 'test'
6d67cf3 translate-all: remove redundant !tcg_enabled check in dump_exec_info
46b92a9 vl: fix breakage of -tb-size
4c7de34 nbd: Implement NBD_INFO_BLOCK_SIZE on client
280da19 nbd: Implement NBD_INFO_BLOCK_SIZE on server
8abe2ce nbd: Implement NBD_OPT_GO on client
0a397be nbd: Implement NBD_OPT_GO on server
2bbad3f nbd: Refactor reply to NBD_OPT_EXPORT_NAME
474ef00 nbd: Simplify trace of client flags in negotiation
080f569 nbd: Expose and debug more NBD constants
c5ea916 nbd: Don't bother tracing an NBD_OPT_ABORT response failure
8921348 nbd: Create struct for tracking export info
c36ec9b memory/iommu: introduce IOMMUMemoryRegionClass
9897b91 memory/iommu: QOM'fy IOMMU MemoryRegion
eb1a75c chardev: fix parallel device can't be reconnect
a862860 gdbstub: don't fail on vCont; C04:0; c packets
d47bd46 qom/cpu: remove host_tid field
4220a85 gdbstub: rename cpu_index -> cpu_gdb_index
2810341 gdbstub: modernise DEBUG_GDB
3b7ce63 mttcg/i386: Patch instruction using async_safe_* framework
bdbca69 Revert "exec.c: Fix breakpoint invalidation race"
d060d0e exec: use qemu_ram_ptr_length to access guest ram
c76c3bb serial: chardev hotswap support
79796d4 serial: move TIOCM update to a separate function
be08fcf virtio-console: chardev hotswap support
e522bda hmp: add hmp analogue for qmp-chardev-change
64ce47e test-char: add hotswap test
e54fca6 test-char: split char_file_test
d971065 test-char: split char_udp_test
b823a3b test-char: destroy chardev-udp after test
e7ba7f5 char: avoid chardevice direct access
4638b74 char: forbid direct chardevice access for hotswap devices
f560498 char: chardevice hotswap
919f86c char: add backend hotswap handler
d00a58a char: move QemuOpts->ChardevBackend translation to a separate func
97d7b48 chardev: block during sync read
e5b1de4 MAINTAINERS: add entry for "Unimplemented" device
d55179c MAINTAINERS: update TCI entry
e6b5227 MAINTAINERS: update Xen entries
b35e727 MAINTAINERS: update KVM entries
4b2ee70 MAINTAINERS: update TCG entries
cd26684 build: add -Wexpansion-to-defined
=== OUTPUT BEGIN ===
Checking PATCH 1/41: build: add -Wexpansion-to-defined...
Checking PATCH 2/41: MAINTAINERS: update TCG entries...
Checking PATCH 3/41: MAINTAINERS: update KVM entries...
Checking PATCH 4/41: MAINTAINERS: update Xen entries...
Checking PATCH 5/41: MAINTAINERS: update TCI entry...
Checking PATCH 6/41: MAINTAINERS: add entry for "Unimplemented" device...
Checking PATCH 7/41: chardev: block during sync read...
Checking PATCH 8/41: char: move QemuOpts->ChardevBackend translation to a separate func...
Checking PATCH 9/41: char: add backend hotswap handler...
WARNING: line over 80 characters
#725: FILE: target/xtensa/xtensa-semi.c:161:
+ qemu_chr_fe_set_handlers(&console, NULL, NULL, NULL, NULL, NULL, NULL, true);
total: 0 errors, 1 warnings, 544 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 10/41: char: chardevice hotswap...
Checking PATCH 11/41: char: forbid direct chardevice access for hotswap devices...
Checking PATCH 12/41: char: avoid chardevice direct access...
Checking PATCH 13/41: test-char: destroy chardev-udp after test...
Checking PATCH 14/41: test-char: split char_udp_test...
Checking PATCH 15/41: test-char: split char_file_test...
Checking PATCH 16/41: test-char: add hotswap test...
Checking PATCH 17/41: hmp: add hmp analogue for qmp-chardev-change...
Checking PATCH 18/41: virtio-console: chardev hotswap support...
Checking PATCH 19/41: serial: move TIOCM update to a separate function...
Checking PATCH 20/41: serial: chardev hotswap support...
Checking PATCH 21/41: exec: use qemu_ram_ptr_length to access guest ram...
Checking PATCH 22/41: Revert "exec.c: Fix breakpoint invalidation race"...
Checking PATCH 23/41: mttcg/i386: Patch instruction using async_safe_* framework...
Checking PATCH 24/41: gdbstub: modernise DEBUG_GDB...
Checking PATCH 25/41: gdbstub: rename cpu_index -> cpu_gdb_index...
Checking PATCH 26/41: qom/cpu: remove host_tid field...
Checking PATCH 27/41: gdbstub: don't fail on vCont; C04:0; c packets...
Checking PATCH 28/41: chardev: fix parallel device can't be reconnect...
Checking PATCH 29/41: memory/iommu: QOM'fy IOMMU MemoryRegion...
ERROR: spaces required around that '*' (ctx:WxO)
#133: FILE: hw/dma/rc4030.c:720:
+DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr)
^
total: 1 errors, 0 warnings, 772 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 30/41: memory/iommu: introduce IOMMUMemoryRegionClass...
Checking PATCH 31/41: nbd: Create struct for tracking export info...
Checking PATCH 32/41: nbd: Don't bother tracing an NBD_OPT_ABORT response failure...
Checking PATCH 33/41: nbd: Expose and debug more NBD constants...
Checking PATCH 34/41: nbd: Simplify trace of client flags in negotiation...
Checking PATCH 35/41: nbd: Refactor reply to NBD_OPT_EXPORT_NAME...
Checking PATCH 36/41: nbd: Implement NBD_OPT_GO on server...
Checking PATCH 37/41: nbd: Implement NBD_OPT_GO on client...
Checking PATCH 38/41: nbd: Implement NBD_INFO_BLOCK_SIZE on server...
Checking PATCH 39/41: nbd: Implement NBD_INFO_BLOCK_SIZE on client...
Checking PATCH 40/41: vl: fix breakage of -tb-size...
Checking PATCH 41/41: translate-all: remove redundant !tcg_enabled check in dump_exec_info...
=== OUTPUT END ===
Test command exited with code: 1
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze
2017-07-13 16:05 ` [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze no-reply
@ 2017-07-13 17:01 ` Paolo Bonzini
0 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2017-07-13 17:01 UTC (permalink / raw)
To: qemu-devel; +Cc: famz
On 13/07/2017 18:05, no-reply@patchew.org wrote:
> Hi,
>
> This series seems to have some coding style problems. See output below for
> more information:
>
False positive due to non-camelcase type in hw/dma/rc4030.c.
> Checking PATCH 29/41: memory/iommu: QOM'fy IOMMU MemoryRegion...
> ERROR: spaces required around that '*' (ctx:WxO)
> #133: FILE: hw/dma/rc4030.c:720:
> +DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr)
Thanks,
Paolo
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PULL 23/41] mttcg/i386: Patch instruction using async_safe_* framework
2017-07-13 15:16 ` Alex Bennée
@ 2017-07-14 8:24 ` Thomas Huth
0 siblings, 0 replies; 46+ messages in thread
From: Thomas Huth @ 2017-07-14 8:24 UTC (permalink / raw)
To: Alex Bennée, Paolo Bonzini; +Cc: Peter Maydell, Pranith Kumar, qemu-devel
On 13.07.2017 17:16, Alex Bennée wrote:
>
> Paolo Bonzini <pbonzini@redhat.com> writes:
>
>> From: Pranith Kumar <bobby.prani@gmail.com>
>>
>> In mttcg, calling pause_all_vcpus() during execution from the
>> generated TBs causes a deadlock if some vCPU is waiting for exclusive
>> execution in start_exclusive(). Fix this by using the aync_safe_*
>> framework instead of pausing vcpus for patching instructions.
>>
>> CC: Paolo Bonzini <pbonzini@redhat.com>
>> CC: Peter Maydell <peter.maydell@linaro.org>
>> Reviewed-by: Richard Henderson <rth@twiddle.net>
>> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
>
> Looks like some UTF-8 mangling has occurred somewhere here.
Not sure whether it would help here, but I had a patch for checkpatch.pl
posted a while ago that should at least help to catch some of the UTF-8
problems:
https://lists.gnu.org/archive/html/qemu-devel/2017-01/msg05741.html
Maybe we should at least include that (without the final two MAINTAINERS
patches in that series)?
Thomas
^ permalink raw reply [flat|nested] 46+ messages in thread
end of thread, other threads:[~2017-07-14 8:25 UTC | newest]
Thread overview: 46+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-13 14:23 [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 01/41] build: add -Wexpansion-to-defined Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 02/41] MAINTAINERS: update TCG entries Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 03/41] MAINTAINERS: update KVM entries Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 04/41] MAINTAINERS: update Xen entries Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 05/41] MAINTAINERS: update TCI entry Paolo Bonzini
2017-07-13 14:23 ` [Qemu-devel] [PULL 06/41] MAINTAINERS: add entry for "Unimplemented" device Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 07/41] chardev: block during sync read Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 08/41] char: move QemuOpts->ChardevBackend translation to a separate func Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 09/41] char: add backend hotswap handler Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 10/41] char: chardevice hotswap Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 11/41] char: forbid direct chardevice access for hotswap devices Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 12/41] char: avoid chardevice direct access Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 13/41] test-char: destroy chardev-udp after test Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 14/41] test-char: split char_udp_test Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 15/41] test-char: split char_file_test Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 16/41] test-char: add hotswap test Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 17/41] hmp: add hmp analogue for qmp-chardev-change Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 18/41] virtio-console: chardev hotswap support Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 19/41] serial: move TIOCM update to a separate function Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 20/41] serial: chardev hotswap support Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 21/41] exec: use qemu_ram_ptr_length to access guest ram Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 22/41] Revert "exec.c: Fix breakpoint invalidation race" Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 23/41] mttcg/i386: Patch instruction using async_safe_* framework Paolo Bonzini
2017-07-13 15:16 ` Alex Bennée
2017-07-14 8:24 ` Thomas Huth
2017-07-13 14:24 ` [Qemu-devel] [PULL 24/41] gdbstub: modernise DEBUG_GDB Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 25/41] gdbstub: rename cpu_index -> cpu_gdb_index Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 26/41] qom/cpu: remove host_tid field Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 27/41] gdbstub: don't fail on vCont; C04:0; c packets Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 28/41] chardev: fix parallel device can't be reconnect Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 29/41] memory/iommu: QOM'fy IOMMU MemoryRegion Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 30/41] memory/iommu: introduce IOMMUMemoryRegionClass Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 31/41] nbd: Create struct for tracking export info Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 32/41] nbd: Don't bother tracing an NBD_OPT_ABORT response failure Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 33/41] nbd: Expose and debug more NBD constants Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 34/41] nbd: Simplify trace of client flags in negotiation Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 35/41] nbd: Refactor reply to NBD_OPT_EXPORT_NAME Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 36/41] nbd: Implement NBD_OPT_GO on server Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 37/41] nbd: Implement NBD_OPT_GO on client Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 38/41] nbd: Implement NBD_INFO_BLOCK_SIZE on server Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 39/41] nbd: Implement NBD_INFO_BLOCK_SIZE on client Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 40/41] vl: fix breakage of -tb-size Paolo Bonzini
2017-07-13 14:24 ` [Qemu-devel] [PULL 41/41] translate-all: remove redundant !tcg_enabled check in dump_exec_info Paolo Bonzini
2017-07-13 16:05 ` [Qemu-devel] [PULL 00/41] Misc patches for QEMU 2.10 soft freeze no-reply
2017-07-13 17:01 ` Paolo Bonzini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).