summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.objs11
-rwxr-xr-xconfigure260
-rw-r--r--docs/usb2.txt20
-rw-r--r--hw/net/vmxnet3.c11
-rw-r--r--hw/net/vmxnet3.h11
-rw-r--r--hw/usb/bus.c2
-rw-r--r--hw/usb/dev-hid.c2
-rw-r--r--hw/usb/dev-hub.c12
-rw-r--r--hw/usb/hcd-xhci.c28
-rw-r--r--hw/usb/redirect.c37
-rw-r--r--include/hw/usb.h1
-rw-r--r--qemu-char.c17
-rw-r--r--qga/commands-win32.c56
-rw-r--r--qga/main.c8
-rw-r--r--qga/qapi-schema.json18
-rw-r--r--tests/Makefile14
-rw-r--r--trace-events1
17 files changed, 298 insertions, 211 deletions
diff --git a/Makefile.objs b/Makefile.objs
index f99841ce54..e568c018b3 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -16,16 +16,7 @@ block-obj-y += qapi-types.o qapi-visit.o
block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
block-obj-y += qemu-coroutine-sleep.o
-ifeq ($(CONFIG_UCONTEXT_COROUTINE),y)
-block-obj-$(CONFIG_POSIX) += coroutine-ucontext.o
-else
-ifeq ($(CONFIG_SIGALTSTACK_COROUTINE),y)
-block-obj-$(CONFIG_POSIX) += coroutine-sigaltstack.o
-else
-block-obj-$(CONFIG_POSIX) += coroutine-gthread.o
-endif
-endif
-block-obj-$(CONFIG_WIN32) += coroutine-win32.o
+block-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
diff --git a/configure b/configure
index e3279ed8b7..1ed939a3ac 100755
--- a/configure
+++ b/configure
@@ -27,6 +27,17 @@ printf " '%s'" "$0" "$@" >> config.log
echo >> config.log
echo "#" >> config.log
+error_exit() {
+ echo
+ echo "ERROR: $1"
+ while test -n "$2"; do
+ echo " $2"
+ shift
+ done
+ echo
+ exit 1
+}
+
do_cc() {
# Run the compiler, capturing its output to the log.
echo $cc "$@" >> config.log
@@ -46,11 +57,10 @@ do_cc() {
esac
echo $cc -Werror "$@" >> config.log
$cc -Werror "$@" >> config.log 2>&1 && return $?
- echo "ERROR: configure test passed without -Werror but failed with -Werror."
- echo "This is probably a bug in the configure script. The failing command"
- echo "will be at the bottom of config.log."
- echo "You can run configure with --disable-werror to bypass this check."
- exit 1
+ error_exit "configure test passed without -Werror but failed with -Werror." \
+ "This is probably a bug in the configure script. The failing command" \
+ "will be at the bottom of config.log." \
+ "You can run configure with --disable-werror to bypass this check."
}
compile_object() {
@@ -494,11 +504,10 @@ SunOS)
LDFLAGS="-L/opt/SUNWspro/prod/lib -R/opt/SUNWspro/prod/lib $LDFLAGS"
LIBS="-lsunmath $LIBS"
else
- echo "QEMU will not link correctly on Solaris 8/X86 or 9/x86 without"
- echo "libsunmath from the Sun Studio compilers tools, due to a lack of"
- echo "C99 math features in libm.so in Solaris 8/x86 and Solaris 9/x86"
- echo "Studio 11 can be downloaded from www.sun.com."
- exit 1
+ error_exit "QEMU will not link correctly on Solaris 8/X86 or 9/x86 without" \
+ "libsunmath from the Sun Studio compilers tools, due to a lack of" \
+ "C99 math features in libm.so in Solaris 8/x86 and Solaris 9/x86" \
+ "Studio 11 can be downloaded from www.sun.com."
fi
fi
fi
@@ -1185,8 +1194,7 @@ if test "$ARCH" = "unknown"; then
echo "Unsupported CPU = $cpu, will use TCG with TCI (experimental)"
ARCH=tci
else
- echo "Unsupported CPU = $cpu, try --enable-tcg-interpreter"
- exit 1
+ error_exit "Unsupported CPU = $cpu, try --enable-tcg-interpreter"
fi
fi
@@ -1198,8 +1206,7 @@ EOF
if compile_object ; then
: C compiler works ok
else
- echo "ERROR: \"$cc\" either does not exist or does not work"
- exit 1
+ error_exit "\"$cc\" either does not exist or does not work"
fi
# Consult white-list to determine whether to enable werror
@@ -1254,8 +1261,7 @@ fi
if test "$static" = "yes" ; then
if test "$pie" = "yes" ; then
- echo "static and pie are mutually incompatible"
- exit 1
+ error_exit "static and pie are mutually incompatible"
else
pie="no"
fi
@@ -1294,8 +1300,7 @@ EOF
fi
else
if test "$pie" = "yes"; then
- echo "PIE not available due to missing toolchain support"
- exit 1
+ error_exit "PIE not available due to missing toolchain support"
else
echo "Disabling PIE due to missing toolchain support"
pie="no"
@@ -1310,40 +1315,36 @@ if test "$solaris" = "yes" ; then
if has $install; then
:
else
- echo "Solaris install program not found. Use --install=/usr/ucb/install or"
- echo "install fileutils from www.blastwave.org using pkg-get -i fileutils"
- echo "to get ginstall which is used by default (which lives in /opt/csw/bin)"
- exit 1
+ error_exit "Solaris install program not found. Use --install=/usr/ucb/install or" \
+ "install fileutils from www.blastwave.org using pkg-get -i fileutils" \
+ "to get ginstall which is used by default (which lives in /opt/csw/bin)"
fi
if test "`path_of $install`" = "/usr/sbin/install" ; then
- echo "Error: Solaris /usr/sbin/install is not an appropriate install program."
- echo "try ginstall from the GNU fileutils available from www.blastwave.org"
- echo "using pkg-get -i fileutils, or use --install=/usr/ucb/install"
- exit 1
+ error_exit "Solaris /usr/sbin/install is not an appropriate install program." \
+ "try ginstall from the GNU fileutils available from www.blastwave.org" \
+ "using pkg-get -i fileutils, or use --install=/usr/ucb/install"
fi
if has ar; then
:
else
- echo "Error: No path includes ar"
if test -f /usr/ccs/bin/ar ; then
- echo "Add /usr/ccs/bin to your path and rerun configure"
+ error_exit "No path includes ar" \
+ "Add /usr/ccs/bin to your path and rerun configure"
fi
- exit 1
+ error_exit "No path includes ar"
fi
fi
if ! has $python; then
- echo "Python not found. Use --python=/path/to/python"
- exit 1
+ error_exit "Python not found. Use --python=/path/to/python"
fi
# Note that if the Python conditional here evaluates True we will exit
# with status 1 which is a shell 'false' value.
if ! "$python" -c 'import sys; sys.exit(sys.version_info < (2,4) or sys.version_info >= (3,))'; then
- echo "Cannot use '$python', Python 2.4 or later is required."
- echo "Note that Python 3 or later is not yet supported."
- echo "Use --python=/path/to/python to specify a supported Python."
- exit 1
+ error_exit "Cannot use '$python', Python 2.4 or later is required." \
+ "Note that Python 3 or later is not yet supported." \
+ "Use --python=/path/to/python to specify a supported Python."
fi
if test -z "${target_list+xxx}" ; then
@@ -1362,11 +1363,8 @@ esac
feature_not_found() {
feature=$1
- echo "ERROR"
- echo "ERROR: User requested feature $feature"
- echo "ERROR: configure was not able to find it"
- echo "ERROR"
- exit 1;
+ error_exit "User requested feature $feature" \
+ "configure was not able to find it"
}
if test -z "$cross_prefix" ; then
@@ -1408,8 +1406,7 @@ fi
# pkg-config probe
if ! has "$pkg_config_exe"; then
- echo "Error: pkg-config binary '$pkg_config_exe' not found"
- exit 1
+ error_exit "pkg-config binary '$pkg_config_exe' not found"
fi
##########################################
@@ -1448,11 +1445,8 @@ EOF
if compile_prog "" "-lz" ; then
:
else
- echo
- echo "Error: zlib check failed"
- echo "Make sure to have the zlib libs and headers installed."
- echo
- exit 1
+ error_exit "zlib check failed" \
+ "Make sure to have the zlib libs and headers installed."
fi
fi
@@ -1629,14 +1623,12 @@ if test "$xen_pci_passthrough" != "no"; then
xen_pci_passthrough=yes
else
if test "$xen_pci_passthrough" = "yes"; then
- echo "ERROR"
- echo "ERROR: User requested feature Xen PCI Passthrough"
- echo "ERROR: but this feature require /sys from Linux"
if test "$xen_ctrl_version" -lt 340; then
- echo "ERROR: This feature does not work with Xen 3.3"
+ error_exit "User requested feature Xen PCI Passthrough" \
+ "This feature does not work with Xen 3.3"
fi
- echo "ERROR"
- exit 1;
+ error_exit "User requested feature Xen PCI Passthrough" \
+ " but this feature requires /sys from Linux"
fi
xen_pci_passthrough=no
fi
@@ -2010,11 +2002,8 @@ EOF
if compile_prog "$cfl" "$lib" ; then
:
else
- echo
- echo "Error: $drv check failed"
- echo "Make sure to have the $drv libs and headers installed."
- echo
- exit 1
+ error_exit "$drv check failed" \
+ "Make sure to have the $drv libs and headers installed."
fi
}
@@ -2029,11 +2018,8 @@ for drv in $audio_drv_list; do
fmod)
if test -z $fmod_lib || test -z $fmod_inc; then
- echo
- echo "Error: You must specify path to FMOD library and headers"
- echo "Example: --fmod-inc=/path/include/fmod --fmod-lib=/path/lib/libfmod-3.74.so"
- echo
- exit 1
+ error_exit "You must specify path to FMOD library and headers" \
+ "Example: --fmod-inc=/path/include/fmod --fmod-lib=/path/lib/libfmod-3.74.so"
fi
audio_drv_probe $drv fmod.h $fmod_lib "return FSOUND_GetVersion();" "-I $fmod_inc"
libs_softmmu="$fmod_lib $libs_softmmu"
@@ -2076,11 +2062,8 @@ for drv in $audio_drv_list; do
*)
echo "$audio_possible_drivers" | grep -q "\<$drv\>" || {
- echo
- echo "Error: Unknown driver '$drv' selected"
- echo "Possible drivers are: $audio_possible_drivers"
- echo
- exit 1
+ error_exit "Unknown driver '$drv' selected" \
+ "Possible drivers are: $audio_possible_drivers"
}
;;
esac
@@ -2209,8 +2192,7 @@ then
LIBS="$glib_libs $LIBS"
libs_qga="$glib_libs $libs_qga"
else
- echo "glib-$glib_req_ver required to compile QEMU"
- exit 1
+ error_exit "glib-$glib_req_ver required to compile QEMU"
fi
##########################################
@@ -2227,11 +2209,10 @@ if test "$pixman" = ""; then
fi
if test "$pixman" = "none"; then
if test "$want_tools" != "no" -o "$softmmu" != "no"; then
- echo "ERROR: pixman disabled but system emulation or tools build"
- echo " enabled. You can turn off pixman only if you also"
- echo " disable all system emulation targets and the tools"
- echo " build with '--disable-tools --disable-system'."
- exit 1
+ error_exit "pixman disabled but system emulation or tools build" \
+ "enabled. You can turn off pixman only if you also" \
+ "disable all system emulation targets and the tools" \
+ "build with '--disable-tools --disable-system'."
fi
pixman_cflags=
pixman_libs=
@@ -2240,12 +2221,11 @@ elif test "$pixman" = "system"; then
pixman_libs=`$pkg_config --libs pixman-1 2>/dev/null`
else
if test ! -d ${source_path}/pixman/pixman; then
- echo "ERROR: pixman not present. Your options:"
- echo " (1) Preferred: Install the pixman devel package (any recent"
- echo " distro should have packages as Xorg needs pixman too)."
- echo " (2) Fetch the pixman submodule, using:"
- echo " git submodule update --init pixman"
- exit 1
+ error_exit "pixman not present. Your options:" \
+ " (1) Preferred: Install the pixman devel package (any recent" \
+ " distro should have packages as Xorg needs pixman too)." \
+ " (2) Fetch the pixman submodule, using:" \
+ " git submodule update --init pixman"
fi
mkdir -p pixman/pixman
pixman_cflags="-I\$(SRC_PATH)/pixman/pixman -I\$(BUILD_DIR)/pixman/pixman"
@@ -2304,11 +2284,8 @@ else
fi
if test "$mingw32" != yes -a "$pthread" = no; then
- echo
- echo "Error: pthread check failed"
- echo "Make sure to have the pthread libs and headers installed."
- echo
- exit 1
+ error_exit "pthread check failed" \
+ "Make sure to have the pthread libs and headers installed."
fi
##########################################
@@ -2363,8 +2340,7 @@ fi
if test "$virtio_blk_data_plane" = "yes" -a \
"$linux_aio" != "yes" ; then
- echo "Error: virtio-blk-data-plane requires Linux AIO, please try --enable-linux-aio"
- exit 1
+ error_exit "virtio-blk-data-plane requires Linux AIO, please try --enable-linux-aio"
elif test -z "$virtio_blk_data_plane" ; then
virtio_blk_data_plane=$linux_aio
fi
@@ -2861,10 +2837,7 @@ elif compile_prog "" "-lm" ; then
LIBS="-lm $LIBS"
libs_qga="-lm $libs_qga"
else
- echo
- echo "Error: libm check failed"
- echo
- exit 1
+ error_exit "libm check failed"
fi
##########################################
@@ -3040,11 +3013,8 @@ fi
$python "$source_path/scripts/tracetool.py" "--backend=$trace_backend" --check-backend > /dev/null 2> /dev/null
if test "$?" -ne 0 ; then
- echo
- echo "Error: invalid trace backend"
- echo "Please choose a supported trace backend."
- echo
- exit 1
+ error_exit "invalid trace backend" \
+ "Please choose a supported trace backend."
fi
##########################################
@@ -3059,10 +3029,7 @@ EOF
LIBS="-lust -lurcu-bp $LIBS"
libs_qga="-lust -lurcu-bp $libs_qga"
else
- echo
- echo "Error: Trace backend 'ust' missing libust header files"
- echo
- exit 1
+ error_exit "Trace backend 'ust' missing libust header files"
fi
fi
@@ -3070,10 +3037,7 @@ fi
# For 'dtrace' backend, test if 'dtrace' command is present
if test "$trace_backend" = "dtrace"; then
if ! has 'dtrace' ; then
- echo
- echo "Error: dtrace command is not found in PATH $PATH"
- echo
- exit 1
+ error_exit "dtrace command is not found in PATH $PATH"
fi
trace_backend_stap="no"
if has 'stap' ; then
@@ -3107,34 +3071,58 @@ fi
##########################################
# check and set a backend for coroutine
-# default is ucontext, but always fallback to gthread
-# windows autodetected by make
-if test "$coroutine" = "" -o "$coroutine" = "ucontext"; then
- if test "$darwin" != "yes"; then
- cat > $TMPC << EOF
+# We prefer ucontext, but it's not always possible. The fallback
+# is sigcontext. gthread is not selectable except explicitly, because
+# it is not functional enough to run QEMU proper. (It is occasionally
+# useful for debugging purposes.) On Windows the only valid backend
+# is the Windows-specific one.
+
+ucontext_works=no
+if test "$darwin" != "yes"; then
+ cat > $TMPC << EOF
#include <ucontext.h>
#ifdef __stub_makecontext
#error Ignoring glibc stub makecontext which will always fail
#endif
int main(void) { makecontext(0, 0, 0); return 0; }
EOF
- if compile_prog "" "" ; then
- coroutine_backend=ucontext
- else
- coroutine_backend=gthread
- fi
+ if compile_prog "" "" ; then
+ ucontext_works=yes
+ fi
+fi
+
+if test "$coroutine" = ""; then
+ if test "$mingw32" = "yes"; then
+ coroutine=win32
+ elif test "$ucontext_works" = "yes"; then
+ coroutine=ucontext
+ else
+ coroutine=sigaltstack
fi
-elif test "$coroutine" = "gthread" ; then
- coroutine_backend=gthread
-elif test "$coroutine" = "windows" ; then
- coroutine_backend=windows
-elif test "$coroutine" = "sigaltstack" ; then
- coroutine_backend=sigaltstack
else
- echo
- echo "Error: unknown coroutine backend $coroutine"
- echo
- exit 1
+ case $coroutine in
+ windows)
+ if test "$mingw32" != "yes"; then
+ error_exit "'windows' coroutine backend only valid for Windows"
+ fi
+ # Unfortunately the user visible backend name doesn't match the
+ # coroutine-*.c filename for this case, so we have to adjust it here.
+ coroutine=win32
+ ;;
+ ucontext)
+ if test "$ucontext_works" != "yes"; then
+ feature_not_found "ucontext"
+ fi
+ ;;
+ gthread|sigaltstack)
+ if test "$mingw32" = "yes"; then
+ error_exit "only the 'windows' coroutine backend is valid for Windows"
+ fi
+ ;;
+ *)
+ error_exit "unknown coroutine backend $coroutine"
+ ;;
+ esac
fi
##########################################
@@ -3319,8 +3307,7 @@ if test "$softmmu" = yes ; then
tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)"
else
if test "$virtfs" = yes; then
- echo "VirtFS is supported only on Linux and requires libcap-devel and libattr-devel"
- exit 1
+ error_exit "VirtFS is supported only on Linux and requires libcap-devel and libattr-devel"
fi
virtfs=no
fi
@@ -3442,7 +3429,7 @@ echo "GLX support $glx"
echo "libiscsi support $libiscsi"
echo "build guest agent $guest_agent"
echo "seccomp support $seccomp"
-echo "coroutine backend $coroutine_backend"
+echo "coroutine backend $coroutine"
echo "GlusterFS support $glusterfs"
echo "virtio-blk-data-plane $virtio_blk_data_plane"
echo "gcov $gcov_tool"
@@ -3775,11 +3762,7 @@ if test "$rbd" = "yes" ; then
echo "CONFIG_RBD=y" >> $config_host_mak
fi
-if test "$coroutine_backend" = "ucontext" ; then
- echo "CONFIG_UCONTEXT_COROUTINE=y" >> $config_host_mak
-elif test "$coroutine_backend" = "sigaltstack" ; then
- echo "CONFIG_SIGALTSTACK_COROUTINE=y" >> $config_host_mak
-fi
+echo "CONFIG_COROUTINE_BACKEND=$coroutine" >> $config_host_mak
if test "$open_by_handle_at" = "yes" ; then
echo "CONFIG_OPEN_BY_HANDLE=y" >> $config_host_mak
@@ -3967,22 +3950,20 @@ case "$target" in
;;
${target_arch2}-linux-user)
if test "$linux" != "yes" ; then
- echo "ERROR: Target '$target' is only available on a Linux host"
- exit 1
+ error_exit "Target '$target' is only available on a Linux host"
fi
target_user_only="yes"
target_linux_user="yes"
;;
${target_arch2}-bsd-user)
if test "$bsd" != "yes" ; then
- echo "ERROR: Target '$target' is only available on a BSD host"
- exit 1
+ error_exit "Target '$target' is only available on a BSD host"
fi
target_user_only="yes"
target_bsd_user="yes"
;;
*)
- echo "ERROR: Target '$target' not recognised"
+ error_exit "Target '$target' not recognised"
exit 1
;;
esac
@@ -4113,8 +4094,7 @@ case "$target_arch2" in
TARGET_ARCH=xtensa
;;
*)
- echo "Unsupported target CPU"
- exit 1
+ error_exit "Unsupported target CPU"
;;
esac
# TARGET_BASE_ARCH needs to be defined after TARGET_ARCH
diff --git a/docs/usb2.txt b/docs/usb2.txt
index 43dacdec28..c7a445afcd 100644
--- a/docs/usb2.txt
+++ b/docs/usb2.txt
@@ -11,7 +11,7 @@ one USB 2.0 bus driven by the EHCI controller. Devices must be
attached to the correct controller manually.
The '-usb' switch will make qemu create the UHCI controller as part of
-the PIIX3 chipset. The USB 1.1 bus will carry the name "usb.0".
+the PIIX3 chipset. The USB 1.1 bus will carry the name "usb-bus.0".
You can use the standard -device switch to add a EHCI controller to
your virtual machine. It is strongly recommended to specify an ID for
@@ -27,7 +27,7 @@ a complete example:
-drive if=none,id=usbstick,file=/path/to/image \
-usb \
-device usb-ehci,id=ehci \
- -device usb-tablet,bus=usb.0 \
+ -device usb-tablet,bus=usb-bus.0 \
-device usb-storage,bus=ehci.0,drive=usbstick
This attaches a usb tablet to the UHCI adapter and a usb mass storage
@@ -88,22 +88,22 @@ ports (1-4), the emulated (1.1) USB hub has eight ports.
Plugging a tablet into UHCI port 1 works like this:
- -device usb-tablet,bus=usb.0,port=1
+ -device usb-tablet,bus=usb-bus.0,port=1
Plugging a hub into UHCI port 2 works like this:
- -device usb-hub,bus=usb.0,port=2
+ -device usb-hub,bus=usb-bus.0,port=2
Plugging a virtual usb stick into port 4 of the hub just plugged works
this way:
- -device usb-storage,bus=usb.0,port=2.4,drive=...
+ -device usb-storage,bus=usb-bus.0,port=2.4,drive=...
You can do basically the same in the monitor using the device_add
command. If you want to unplug devices too you should specify some
unique id which you can use to refer to the device ...
- (qemu) device_add usb-tablet,bus=usb.0,port=1,id=my-tablet
+ (qemu) device_add usb-tablet,bus=usb-bus.0,port=1,id=my-tablet
(qemu) device_del my-tablet
... when unplugging it with device_del.
@@ -148,10 +148,10 @@ using for testing is bus 1 + port 1 for 2.0 devices and bus 3 + port 1
for 1.1 devices. Passing through any device plugged into that port
and also assign them to the correct bus can be done this way:
- qemu -M pc ${otheroptions} \
- -usb \
- -device usb-ehci,id=ehci \
- -device usb-host,bus=usb.0,hostbus=3,hostport=1 \
+ qemu -M pc ${otheroptions} \
+ -usb \
+ -device usb-ehci,id=ehci \
+ -device usb-host,bus=usb-bus.0,hostbus=3,hostport=1 \
-device usb-host,bus=ehci.0,hostbus=1,hostport=1
enjoy,
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 5916624371..5f483e7f1e 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -1032,6 +1032,7 @@ vmxnet3_indicate_packet(VMXNET3State *s)
is_head = false;
ready_rxcd_pa = new_rxcd_pa;
new_rxcd_pa = 0;
+ num_frags++;
}
if (0 != ready_rxcd_pa) {
@@ -1323,6 +1324,10 @@ static void vmxnet3_activate_device(VMXNET3State *s)
s->max_rx_frags =
VMXNET3_READ_DRV_SHARED16(s->drv_shmem, devRead.misc.maxNumRxSG);
+ if (s->max_rx_frags == 0) {
+ s->max_rx_frags = 1;
+ }
+
VMW_CFPRN("Max RX fragments is %u", s->max_rx_frags);
s->event_int_idx =
@@ -1523,6 +1528,12 @@ static uint64_t vmxnet3_get_command_status(VMXNET3State *s)
VMW_CFPRN("Device active: %" PRIx64, ret);
break;
+ case VMXNET3_CMD_RESET_DEV:
+ case VMXNET3_CMD_QUIESCE_DEV:
+ case VMXNET3_CMD_GET_QUEUE_STATUS:
+ ret = 0;
+ break;
+
case VMXNET3_CMD_GET_LINK:
ret = s->link_status_and_speed;
VMW_CFPRN("Link and speed: %" PRIx64, ret);
diff --git a/hw/net/vmxnet3.h b/hw/net/vmxnet3.h
index 7db0c8f5e0..4eae7c76be 100644
--- a/hw/net/vmxnet3.h
+++ b/hw/net/vmxnet3.h
@@ -37,10 +37,8 @@
#define __packed QEMU_PACKED
#if defined(HOST_WORDS_BIGENDIAN)
-#define const_cpu_to_le64(x) bswap_64(x)
#define __BIG_ENDIAN_BITFIELD
#else
-#define const_cpu_to_le64(x) (x)
#endif
/*
@@ -137,10 +135,10 @@ struct UPT1_RSSConf {
/* features */
enum {
- UPT1_F_RXCSUM = const_cpu_to_le64(0x0001), /* rx csum verification */
- UPT1_F_RSS = const_cpu_to_le64(0x0002),
- UPT1_F_RXVLAN = const_cpu_to_le64(0x0004), /* VLAN tag stripping */
- UPT1_F_LRO = const_cpu_to_le64(0x0008),
+ UPT1_F_RXCSUM = 0x0001, /* rx csum verification */
+ UPT1_F_RSS = 0x0002,
+ UPT1_F_RXVLAN = 0x0004, /* VLAN tag stripping */
+ UPT1_F_LRO = 0x0008,
};
/* all registers are 32 bit wide */
@@ -752,7 +750,6 @@ struct Vmxnet3_DriverShared {
#undef __le32
#undef __le64
#undef __packed
-#undef const_cpu_to_le64
#if defined(HOST_WORDS_BIGENDIAN)
#undef __BIG_ENDIAN_BITFIELD
#endif
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index e58cd9ade2..b10c290cf4 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -341,8 +341,10 @@ void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
if (upstream) {
snprintf(downstream->path, sizeof(downstream->path), "%s.%d",
upstream->path, portnr);
+ downstream->hubcount = upstream->hubcount + 1;
} else {
snprintf(downstream->path, sizeof(downstream->path), "%d", portnr);
+ downstream->hubcount = 0;
}
}
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index 5f3a4b401e..b48899d500 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -236,7 +236,7 @@ static const USBDescDevice desc_device_tablet2 = {
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.iConfiguration = STR_CONFIG_TABLET,
- .bmAttributes = 0xa0,
+ .bmAttributes = 0x80,
.bMaxPower = 50,
.nif = 1,
.ifs = &desc_iface_tablet2,
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 504c98c350..0b71abd028 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -25,6 +25,7 @@
#include "trace.h"
#include "hw/usb.h"
#include "hw/usb/desc.h"
+#include "qemu/error-report.h"
#define NUM_PORTS 8
@@ -32,6 +33,7 @@ typedef struct USBHubPort {
USBPort port;
uint16_t wPortStatus;
uint16_t wPortChange;
+ uint16_t wPortChange_reported;
} USBHubPort;
typedef struct USBHubState {
@@ -466,8 +468,11 @@ static void usb_hub_handle_data(USBDevice *dev, USBPacket *p)
status = 0;
for(i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i];
- if (port->wPortChange)
+ if (port->wPortChange &&
+ port->wPortChange_reported != port->wPortChange) {
status |= (1 << (i + 1));
+ }
+ port->wPortChange_reported = port->wPortChange;
}
if (status != 0) {
for(i = 0; i < n; i++) {
@@ -514,6 +519,11 @@ static int usb_hub_initfn(USBDevice *dev)
USBHubPort *port;
int i;
+ if (dev->port->hubcount == 5) {
+ error_report("usb hub chain too deep");
+ return -1;
+ }
+
usb_desc_create_serial(dev);
usb_desc_init(dev);
s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 5aa342bda5..efd4b0dbde 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -452,7 +452,6 @@ struct XHCIState {
MemoryRegion mem_oper;
MemoryRegion mem_runtime;
MemoryRegion mem_doorbell;
- const char *name;
unsigned int devaddr;
/* properties */
@@ -1172,8 +1171,6 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
uint32_t ctx[5];
uint32_t ctx2[2];
- fprintf(stderr, "%s: epid %d, state %d\n",
- __func__, epctx->epid, state);
xhci_dma_read_u32s(xhci, epctx->pctx, ctx, sizeof(ctx));
ctx[0] &= ~EP_STATE_MASK;
ctx[0] |= state;
@@ -2568,7 +2565,7 @@ static void xhci_process_commands(XHCIState *xhci)
}
break;
default:
- fprintf(stderr, "xhci: unimplemented command %d\n", type);
+ trace_usb_xhci_unimplemented("command", type);
event.ccode = CC_TRB_ERROR;
break;
}
@@ -2767,7 +2764,7 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size)
ret = 0x00000000; /* reserved */
break;
default:
- fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", (int)reg);
+ trace_usb_xhci_unimplemented("cap read", reg);
ret = 0;
}
@@ -2790,8 +2787,7 @@ static uint64_t xhci_port_read(void *ptr, hwaddr reg, unsigned size)
break;
case 0x0c: /* reserved */
default:
- fprintf(stderr, "xhci_port_read (port %d): reg 0x%x unimplemented\n",
- port->portnr, (uint32_t)reg);
+ trace_usb_xhci_unimplemented("port read", reg);
ret = 0;
}
@@ -2831,8 +2827,7 @@ static void xhci_port_write(void *ptr, hwaddr reg,
case 0x04: /* PORTPMSC */
case 0x08: /* PORTLI */
default:
- fprintf(stderr, "xhci_port_write (port %d): reg 0x%x unimplemented\n",
- port->portnr, (uint32_t)reg);
+ trace_usb_xhci_unimplemented("port write", reg);
}
}
@@ -2870,7 +2865,7 @@ static uint64_t xhci_oper_read(void *ptr, hwaddr reg, unsigned size)
ret = xhci->config;
break;
default:
- fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", (int)reg);
+ trace_usb_xhci_unimplemented("oper read", reg);
ret = 0;
}
@@ -2935,7 +2930,7 @@ static void xhci_oper_write(void *ptr, hwaddr reg,
xhci->config = val & 0xff;
break;
default:
- fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", (int)reg);
+ trace_usb_xhci_unimplemented("oper write", reg);
}
}
@@ -2951,8 +2946,7 @@ static uint64_t xhci_runtime_read(void *ptr, hwaddr reg,
ret = xhci_mfindex_get(xhci) & 0x3fff;
break;
default:
- fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n",
- (int)reg);
+ trace_usb_xhci_unimplemented("runtime read", reg);
break;
}
} else {
@@ -2996,7 +2990,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg,
trace_usb_xhci_runtime_write(reg, val);
if (reg < 0x20) {
- fprintf(stderr, "%s: reg 0x%x unimplemented\n", __func__, (int)reg);
+ trace_usb_xhci_unimplemented("runtime write", reg);
return;
}
@@ -3038,8 +3032,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg,
xhci_events_update(xhci, v);
break;
default:
- fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n",
- (int)reg);
+ trace_usb_xhci_unimplemented("oper write", reg);
}
}
@@ -3290,6 +3283,9 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
if (xhci->numintrs > MAXINTRS) {
xhci->numintrs = MAXINTRS;
}
+ while (xhci->numintrs & (xhci->numintrs - 1)) { /* ! power of 2 */
+ xhci->numintrs++;
+ }
if (xhci->numintrs < 1) {
xhci->numintrs = 1;
}
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index d02a7b94c4..0ddb0818d8 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -104,6 +104,8 @@ struct USBRedirDevice {
/* Data passed from chardev the fd_read cb to the usbredirparser read cb */
const uint8_t *read_buf;
int read_buf_size;
+ /* Active chardev-watch-tag */
+ guint watch;
/* For async handling of close */
QEMUBH *chardev_close_bh;
/* To delay the usb attach in case of quick chardev close + open */
@@ -254,9 +256,21 @@ static int usbredir_read(void *priv, uint8_t *data, int count)
return count;
}
+static gboolean usbredir_write_unblocked(GIOChannel *chan, GIOCondition cond,
+ void *opaque)
+{
+ USBRedirDevice *dev = opaque;
+
+ dev->watch = 0;
+ usbredirparser_do_write(dev->parser);
+
+ return FALSE;
+}
+
static int usbredir_write(void *priv, uint8_t *data, int count)
{
USBRedirDevice *dev = priv;
+ int r;
if (!dev->cs->be_open) {
return 0;
@@ -267,7 +281,17 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
return 0;
}
- return qemu_chr_fe_write(dev->cs, data, count);
+ r = qemu_chr_fe_write(dev->cs, data, count);
+ if (r < count) {
+ if (!dev->watch) {
+ dev->watch = qemu_chr_fe_add_watch(dev->cs, G_IO_OUT,
+ usbredir_write_unblocked, dev);
+ }
+ if (r < 0) {
+ r = 0;
+ }
+ }
+ return r;
}
/*
@@ -1085,6 +1109,10 @@ static void usbredir_chardev_close_bh(void *opaque)
usbredirparser_destroy(dev->parser);
dev->parser = NULL;
}
+ if (dev->watch) {
+ g_source_remove(dev->watch);
+ dev->watch = 0;
+ }
}
static void usbredir_create_parser(USBRedirDevice *dev)
@@ -1317,6 +1345,9 @@ static void usbredir_handle_destroy(USBDevice *udev)
if (dev->parser) {
usbredirparser_destroy(dev->parser);
}
+ if (dev->watch) {
+ g_source_remove(dev->watch);
+ }
free(dev->filter_rules);
}
@@ -1973,6 +2004,10 @@ static int usbredir_post_load(void *priv, int version_id)
{
USBRedirDevice *dev = priv;
+ if (dev->parser == NULL) {
+ return 0;
+ }
+
switch (dev->device_info.speed) {
case usb_redir_speed_low:
dev->dev.speed = USB_SPEED_LOW;
diff --git a/include/hw/usb.h b/include/hw/usb.h
index 1b10684dde..4d9d05e9bc 100644
--- a/include/hw/usb.h
+++ b/include/hw/usb.h
@@ -337,6 +337,7 @@ typedef struct USBPortOps {
struct USBPort {
USBDevice *dev;
int speedmask;
+ int hubcount;
char path[16];
USBPortOps *ops;
void *opaque;
diff --git a/qemu-char.c b/qemu-char.c
index dd410ce40f..eae17fc61c 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -596,9 +596,11 @@ typedef struct IOWatchPoll
{
GSource parent;
+ GIOChannel *channel;
GSource *src;
IOCanReadHandler *fd_can_read;
+ GSourceFunc fd_read;
void *opaque;
} IOWatchPoll;
@@ -611,15 +613,19 @@ static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_)
{
IOWatchPoll *iwp = io_watch_poll_from_source(source);
bool now_active = iwp->fd_can_read(iwp->opaque) > 0;
- bool was_active = g_source_get_context(iwp->src) != NULL;
+ bool was_active = iwp->src != NULL;
if (was_active == now_active) {
return FALSE;
}
if (now_active) {
+ iwp->src = g_io_create_watch(iwp->channel, G_IO_IN | G_IO_ERR | G_IO_HUP);
+ g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL);
g_source_attach(iwp->src, NULL);
} else {
- g_source_remove(g_source_get_id(iwp->src));
+ g_source_destroy(iwp->src);
+ g_source_unref(iwp->src);
+ iwp->src = NULL;
}
return FALSE;
}
@@ -638,7 +644,9 @@ static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback,
static void io_watch_poll_finalize(GSource *source)
{
IOWatchPoll *iwp = io_watch_poll_from_source(source);
+ g_source_destroy(iwp->src);
g_source_unref(iwp->src);
+ iwp->src = NULL;
}
static GSourceFuncs io_watch_poll_funcs = {
@@ -659,8 +667,9 @@ static guint io_add_watch_poll(GIOChannel *channel,
iwp = (IOWatchPoll *) g_source_new(&io_watch_poll_funcs, sizeof(IOWatchPoll));
iwp->fd_can_read = fd_can_read;
iwp->opaque = user_data;
- iwp->src = g_io_create_watch(channel, G_IO_IN | G_IO_ERR | G_IO_HUP);
- g_source_set_callback(iwp->src, (GSourceFunc)fd_read, user_data, NULL);
+ iwp->channel = channel;
+ iwp->fd_read = (GSourceFunc) fd_read;
+ iwp->src = NULL;
return g_source_attach(&iwp->parent, NULL);
}
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index b19be9db48..24e4ad0319 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -22,6 +22,12 @@
#define SHTDN_REASON_FLAG_PLANNED 0x80000000
#endif
+/* multiple of 100 nanoseconds elapsed between windows baseline
+ * (1/1/1601) and Unix Epoch (1/1/1970), accounting for leap years */
+#define W32_FT_OFFSET (10000000ULL * 60 * 60 * 24 * \
+ (365 * (1970 - 1601) + \
+ (1970 - 1601) / 4 - 3))
+
static void acquire_privilege(const char *name, Error **err)
{
HANDLE token;
@@ -280,13 +286,57 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **err)
int64_t qmp_guest_get_time(Error **errp)
{
- error_set(errp, QERR_UNSUPPORTED);
- return -1;
+ SYSTEMTIME ts = {0};
+ int64_t time_ns;
+ FILETIME tf;
+
+ GetSystemTime(&ts);
+ if (ts.wYear < 1601 || ts.wYear > 30827) {
+ error_setg(errp, "Failed to get time");
+ return -1;
+ }
+
+ if (!SystemTimeToFileTime(&ts, &tf)) {
+ error_setg(errp, "Failed to convert system time: %d", (int)GetLastError());
+ return -1;
+ }
+
+ time_ns = ((((int64_t)tf.dwHighDateTime << 32) | tf.dwLowDateTime)
+ - W32_FT_OFFSET) * 100;
+
+ return time_ns;
}
void qmp_guest_set_time(int64_t time_ns, Error **errp)
{
- error_set(errp, QERR_UNSUPPORTED);
+ SYSTEMTIME ts;
+ FILETIME tf;
+ LONGLONG time;
+
+ if (time_ns < 0 || time_ns / 100 > INT64_MAX - W32_FT_OFFSET) {
+ error_setg(errp, "Time %" PRId64 "is invalid", time_ns);
+ return;
+ }
+
+ time = time_ns / 100 + W32_FT_OFFSET;
+
+ tf.dwLowDateTime = (DWORD) time;
+ tf.dwHighDateTime = (DWORD) (time >> 32);
+
+ if (!FileTimeToSystemTime(&tf, &ts)) {
+ error_setg(errp, "Failed to convert system time %d", (int)GetLastError());
+ return;
+ }
+
+ acquire_privilege(SE_SYSTEMTIME_NAME, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+
+ if (!SetSystemTime(&ts)) {
+ error_setg(errp, "Failed to set time to guest: %d", (int)GetLastError());
+ return;
+ }
}
GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
diff --git a/qga/main.c b/qga/main.c
index 74ef7885b2..1841759db2 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -889,9 +889,13 @@ int64_t ga_get_fd_handle(GAState *s, Error **errp)
g_assert(!ga_is_frozen(s));
handle = s->pstate.fd_counter++;
- if (s->pstate.fd_counter < 0) {
- s->pstate.fd_counter = 0;
+
+ /* This should never happen on a reasonable timeframe, as guest-file-open
+ * would have to be issued 2^63 times */
+ if (s->pstate.fd_counter == INT64_MAX) {
+ abort();
}
+
if (!write_persistent_state(&s->pstate, s->pstate_filepath)) {
error_setg(errp, "failed to commit persistent state to disk");
}
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index dac4e6f95f..7155b7ab55 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -2,6 +2,17 @@
##
#
+# General note concerning the use of guest agent interfaces:
+#
+# "unsupported" is a higher-level error than the errors that individual
+# commands might document. The caller should always be prepared to receive
+# QERR_UNSUPPORTED, even if the given command doesn't specify it, or doesn't
+# document any failure mode at all.
+#
+##
+
+##
+#
# Echo back a unique integer value, and prepend to response a
# leading sentinel byte (0xFF) the client can check scan for.
#
@@ -562,9 +573,10 @@
#
# @online: Whether the VCPU is enabled.
#
-# @can-offline: Whether offlining the VCPU is possible. This member is always
-# filled in by the guest agent when the structure is returned,
-# and always ignored on input (hence it can be omitted then).
+# @can-offline: #optional Whether offlining the VCPU is possible. This member
+# is always filled in by the guest agent when the structure is
+# returned, and always ignored on input (hence it can be omitted
+# then).
#
# Since: 1.5
##
diff --git a/tests/Makefile b/tests/Makefile
index 567e36e777..7fa15c6c08 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -24,19 +24,7 @@ gcov-files-test-string-input-visitor-y = qapi/string-input-visitor.c
check-unit-y += tests/test-string-output-visitor$(EXESUF)
gcov-files-test-string-output-visitor-y = qapi/string-output-visitor.c
check-unit-y += tests/test-coroutine$(EXESUF)
-ifeq ($(CONFIG_WIN32),y)
-gcov-files-test-coroutine-y = coroutine-win32.c
-else
-ifeq ($(CONFIG_UCONTEXT_COROUTINE),y)
-gcov-files-test-coroutine-y = coroutine-ucontext.c
-else
-ifeq ($(CONFIG_SIGALTSTACK_COROUTINE),y)
-gcov-files-test-coroutine-y = coroutine-sigaltstack.c
-else
-gcov-files-test-coroutine-y = coroutine-gthread.c
-endif
-endif
-endif
+gcov-files-test-coroutine-y = coroutine-$(CONFIG_COROUTINE_BACKEND).c
check-unit-y += tests/test-visitor-serialization$(EXESUF)
check-unit-y += tests/test-iov$(EXESUF)
gcov-files-test-iov-y = util/iov.c
diff --git a/trace-events b/trace-events
index 7f34112424..412f7e40f8 100644
--- a/trace-events
+++ b/trace-events
@@ -380,6 +380,7 @@ usb_xhci_xfer_nak(void *xfer) "%p"
usb_xhci_xfer_retry(void *xfer) "%p"
usb_xhci_xfer_success(void *xfer, uint32_t bytes) "%p: len %d"
usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d"
+usb_xhci_unimplemented(const char *item, int nr) "%s (0x%x)"
# hw/usb/desc.c
usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"