diff options
50 files changed, 406 insertions, 322 deletions
diff --git a/chardev/char-socket.c b/chardev/char-socket.c index 9061981..06a37c0 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -387,6 +387,9 @@ static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len) static GSource *tcp_chr_add_watch(Chardev *chr, GIOCondition cond) { SocketChardev *s = SOCKET_CHARDEV(chr); + if (!s->ioc) { + return NULL; + } return qio_channel_create_watch(s->ioc, cond); } @@ -449,7 +452,7 @@ static char *qemu_chr_socket_address(SocketChardev *s, const char *prefix) qemu_chr_socket_protocol(s), s->addr->u.inet.host, s->addr->u.inet.port, - s->is_listen ? ",server" : ""); + s->is_listen ? ",server=on" : ""); break; case SOCKET_ADDRESS_TYPE_UNIX: { @@ -467,12 +470,12 @@ static char *qemu_chr_socket_address(SocketChardev *s, const char *prefix) return g_strdup_printf("%sunix:%s%s%s%s", prefix, sa->path, abstract, tight, - s->is_listen ? ",server" : ""); + s->is_listen ? ",server=on" : ""); break; } case SOCKET_ADDRESS_TYPE_FD: return g_strdup_printf("%sfd:%s%s", prefix, s->addr->u.fd.str, - s->is_listen ? ",server" : ""); + s->is_listen ? ",server=on" : ""); break; case SOCKET_ADDRESS_TYPE_VSOCK: return g_strdup_printf("%svsock:%s:%s", prefix, @@ -604,7 +607,7 @@ static char *qemu_chr_compute_filename(SocketChardev *s) case AF_UNIX: return g_strdup_printf("unix:%s%s", ((struct sockaddr_un *)(ss))->sun_path, - s->is_listen ? ",server" : ""); + s->is_listen ? ",server=on" : ""); #endif case AF_INET6: left = "["; @@ -618,7 +621,7 @@ static char *qemu_chr_compute_filename(SocketChardev *s) return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s", qemu_chr_socket_protocol(s), left, shost, right, sserv, - s->is_listen ? ",server" : "", + s->is_listen ? ",server=on" : "", left, phost, right, pserv); default: @@ -463,7 +463,7 @@ skip_meson=no gettext="auto" fuse="auto" fuse_lseek="auto" -multiprocess="no" +multiprocess="auto" malloc_trim="auto" @@ -798,7 +798,6 @@ Linux) linux="yes" linux_user="yes" vhost_user=${default_feature:-yes} - multiprocess=${default_feature:-yes} ;; esac @@ -1558,9 +1557,9 @@ for opt do ;; --disable-fuse-lseek) fuse_lseek="disabled" ;; - --enable-multiprocess) multiprocess="yes" + --enable-multiprocess) multiprocess="enabled" ;; - --disable-multiprocess) multiprocess="no" + --disable-multiprocess) multiprocess="disabled" ;; *) echo "ERROR: unknown option $opt" @@ -1914,7 +1913,7 @@ disabled with --disable-FEATURE, default is enabled if available libdaxctl libdaxctl support fuse FUSE block device export fuse-lseek SEEK_HOLE/SEEK_DATA support for FUSE exports - multiprocess Multiprocess QEMU support + multiprocess Out of process device emulation support NOTE: The object files are built at the place where configure is launched EOF @@ -6089,14 +6088,21 @@ fi if test "$have_mlockall" = "yes" ; then echo "HAVE_MLOCKALL=y" >> $config_host_mak fi -if test "$multiprocess" = "yes" ; then - echo "CONFIG_MULTIPROCESS_ALLOWED=y" >> $config_host_mak -fi if test "$fuzzing" = "yes" ; then # If LIB_FUZZING_ENGINE is set, assume we are running on OSS-Fuzz, and the # needed CFLAGS have already been provided if test -z "${LIB_FUZZING_ENGINE+xxx}" ; then + # Add CFLAGS to tell clang to add fuzzer-related instrumentation to all the + # compiled code. QEMU_CFLAGS="$QEMU_CFLAGS -fsanitize=fuzzer-no-link" + # To build non-fuzzer binaries with --enable-fuzzing, link everything with + # fsanitize=fuzzer-no-link. Otherwise, the linker will be unable to bind + # the fuzzer-related callbacks added by instrumentation. + QEMU_LDFLAGS="$QEMU_LDFLAGS -fsanitize=fuzzer-no-link" + # For the actual fuzzer binaries, we need to link against the libfuzzer + # library. Provide the flags for doing this in FUZZ_EXE_LDFLAGS. The meson + # rule for the fuzzer adds these to the link_args. They need to be + # configurable, to support OSS-Fuzz FUZZ_EXE_LDFLAGS="-fsanitize=fuzzer" else FUZZ_EXE_LDFLAGS="$LIB_FUZZING_ENGINE" @@ -6424,7 +6430,7 @@ NINJA=$ninja $meson setup \ -Dzstd=$zstd -Dseccomp=$seccomp -Dvirtfs=$virtfs -Dcap_ng=$cap_ng \ -Dattr=$attr -Ddefault_devices=$default_devices \ -Ddocs=$docs -Dsphinx_build=$sphinx_build -Dinstall_blobs=$blobs \ - -Dvhost_user_blk_server=$vhost_user_blk_server \ + -Dvhost_user_blk_server=$vhost_user_blk_server -Dmultiprocess=$multiprocess \ -Dfuse=$fuse -Dfuse_lseek=$fuse_lseek -Dguest_agent_msi=$guest_agent_msi \ $(if test "$default_features" = no; then echo "-Dauto_features=disabled"; fi) \ -Dtcg_interpreter=$tcg_interpreter \ diff --git a/docs/COLO-FT.txt b/docs/COLO-FT.txt index bc5fb2a..8d6d53a 100644 --- a/docs/COLO-FT.txt +++ b/docs/COLO-FT.txt @@ -158,15 +158,15 @@ instance. # imagefolder="/mnt/vms/colo-test-primary" -# qemu-system-x86_64 -enable-kvm -cpu qemu64,+kvmclock -m 512 -smp 1 -qmp stdio \ +# qemu-system-x86_64 -enable-kvm -cpu qemu64,kvmclock=on -m 512 -smp 1 -qmp stdio \ -device piix3-usb-uhci -device usb-tablet -name primary \ -netdev tap,id=hn0,vhost=off,helper=/usr/lib/qemu/qemu-bridge-helper \ -device rtl8139,id=e0,netdev=hn0 \ - -chardev socket,id=mirror0,host=0.0.0.0,port=9003,server,nowait \ - -chardev socket,id=compare1,host=0.0.0.0,port=9004,server,wait \ - -chardev socket,id=compare0,host=127.0.0.1,port=9001,server,nowait \ + -chardev socket,id=mirror0,host=0.0.0.0,port=9003,server=on,wait=off \ + -chardev socket,id=compare1,host=0.0.0.0,port=9004,server=on,wait=on \ + -chardev socket,id=compare0,host=127.0.0.1,port=9001,server=on,wait=off \ -chardev socket,id=compare0-0,host=127.0.0.1,port=9001 \ - -chardev socket,id=compare_out,host=127.0.0.1,port=9005,server,nowait \ + -chardev socket,id=compare_out,host=127.0.0.1,port=9005,server=on,wait=off \ -chardev socket,id=compare_out0,host=127.0.0.1,port=9005 \ -object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0 \ -object filter-redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out \ @@ -189,7 +189,7 @@ any IP's here, except for the $primary_ip variable. # qemu-img create -f qcow2 $imagefolder/secondary-hidden.qcow2 10G -# qemu-system-x86_64 -enable-kvm -cpu qemu64,+kvmclock -m 512 -smp 1 -qmp stdio \ +# qemu-system-x86_64 -enable-kvm -cpu qemu64,kvmclock=on -m 512 -smp 1 -qmp stdio \ -device piix3-usb-uhci -device usb-tablet -name secondary \ -netdev tap,id=hn0,vhost=off,helper=/usr/lib/qemu/qemu-bridge-helper \ -device rtl8139,id=e0,netdev=hn0 \ diff --git a/docs/ccid.txt b/docs/ccid.txt index c7fda6d..c97fbd2 100644 --- a/docs/ccid.txt +++ b/docs/ccid.txt @@ -109,7 +109,8 @@ NSS. Registration can be done from Firefox or the command line: on the host specify the ccid-card-passthru device with a suitable chardev: - qemu -chardev socket,server,host=0.0.0.0,port=2001,id=ccid,nowait -usb -device usb-ccid -device ccid-card-passthru,chardev=ccid + qemu -chardev socket,server=on,host=0.0.0.0,port=2001,id=ccid,wait=off \ + -usb -device usb-ccid -device ccid-card-passthru,chardev=ccid on the client run vscclient, built when you built QEMU: @@ -125,7 +126,8 @@ Follow instructions as per #4, except run QEMU and vscclient as follows: Run qemu as per #5, and run vscclient from the "fake-smartcard" directory as follows: - qemu -chardev socket,server,host=0.0.0.0,port=2001,id=ccid,nowait -usb -device usb-ccid -device ccid-card-passthru,chardev=ccid + qemu -chardev socket,server=on,host=0.0.0.0,port=2001,id=ccid,wait=off \ + -usb -device usb-ccid -device ccid-card-passthru,chardev=ccid vscclient -e "db=\"sql:$PWD\" use_hw=no soft=(,Test,CAC,,id-cert,signing-cert,encryption-cert)" <qemu-host> 2001 diff --git a/docs/colo-proxy.txt b/docs/colo-proxy.txt index fa1cef0..1fc38ae 100644 --- a/docs/colo-proxy.txt +++ b/docs/colo-proxy.txt @@ -164,11 +164,11 @@ clearly describe the usage. Primary(ip:3.3.3.3): -netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown -device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66 --chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait --chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait --chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait +-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server=on,wait=off +-chardev socket,id=compare1,host=3.3.3.3,port=9004,server=on,wait=off +-chardev socket,id=compare0,host=3.3.3.3,port=9001,server=on,wait=off -chardev socket,id=compare0-0,host=3.3.3.3,port=9001 --chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait +-chardev socket,id=compare_out,host=3.3.3.3,port=9005,server=on,wait=off -chardev socket,id=compare_out0,host=3.3.3.3,port=9005 -object iothread,id=iothread1 -object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0 @@ -190,11 +190,11 @@ If you want to use virtio-net-pci or other driver with vnet_header: Primary(ip:3.3.3.3): -netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown -device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66 --chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait --chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait --chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait +-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server=on,wait=off +-chardev socket,id=compare1,host=3.3.3.3,port=9004,server=on,wait=off +-chardev socket,id=compare0,host=3.3.3.3,port=9001,server=on,wait=off -chardev socket,id=compare0-0,host=3.3.3.3,port=9001 --chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait +-chardev socket,id=compare_out,host=3.3.3.3,port=9005,server=on,wait=off -chardev socket,id=compare_out0,host=3.3.3.3,port=9005 -object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0,vnet_hdr_support -object filter-redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out,vnet_hdr_support diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt index 258e63b..b1e31d5 100644 --- a/docs/devel/writing-qmp-commands.txt +++ b/docs/devel/writing-qmp-commands.txt @@ -39,7 +39,7 @@ shown here. First, QEMU should be started like this: # qemu-system-TARGET [...] \ - -chardev socket,id=qmp,port=4444,host=localhost,server \ + -chardev socket,id=qmp,port=4444,host=localhost,server=on \ -mon chardev=qmp,mode=control,pretty=on Then, in a different terminal: diff --git a/docs/interop/firmware.json b/docs/interop/firmware.json index 989f10b..9d94cca 100644 --- a/docs/interop/firmware.json +++ b/docs/interop/firmware.json @@ -129,7 +129,7 @@ # "-machine smm=on". (On the "pc-q35-*" machine types of # the @i386 emulation target, @requires-smm presents # further CPU requirements; one combination known to work -# is "-cpu coreduo,-nx".) If the firmware is marked as +# is "-cpu coreduo,nx=off".) If the firmware is marked as # both @secure-boot and @requires-smm, then write # accesses to the pflash chip (NVRAM) that holds the UEFI # variable store must be restricted to code that executes diff --git a/docs/interop/live-block-operations.rst b/docs/interop/live-block-operations.rst index e13f5a2..1073b93 100644 --- a/docs/interop/live-block-operations.rst +++ b/docs/interop/live-block-operations.rst @@ -133,7 +133,7 @@ socket:: -M q35 -nodefaults -m 512 \ -blockdev node-name=node-A,driver=qcow2,file.driver=file,file.node-name=file,file.filename=./a.qcow2 \ -device virtio-blk,drive=node-A,id=virtio0 \ - -monitor stdio -qmp unix:/tmp/qmp-sock,server,nowait + -monitor stdio -qmp unix:/tmp/qmp-sock,server=on,wait=off The ``-blockdev`` command-line option, used above, is available from QEMU 2.9 onwards. In the above invocation, notice the ``node-name`` @@ -698,7 +698,7 @@ it could be located elsewhere):: -M q35 -nodefaults -m 512 \ -blockdev node-name=node-TargetDisk,driver=qcow2,file.driver=file,file.node-name=file,file.filename=./target-disk.qcow2 \ -device virtio-blk,drive=node-TargetDisk,id=virtio0 \ - -S -monitor stdio -qmp unix:./qmp-sock2,server,nowait \ + -S -monitor stdio -qmp unix:./qmp-sock2,server=on,wait=off \ -incoming tcp:localhost:6666 Given the disk image chain on source QEMU:: diff --git a/docs/interop/qmp-intro.txt b/docs/interop/qmp-intro.txt index 9d54a71..1c745a7 100644 --- a/docs/interop/qmp-intro.txt +++ b/docs/interop/qmp-intro.txt @@ -26,7 +26,7 @@ Usage You can use the -qmp option to enable QMP. For example, the following makes QMP available on localhost port 4444: -$ qemu [...] -qmp tcp:localhost:4444,server,nowait +$ qemu [...] -qmp tcp:localhost:4444,server=on,wait=off However, for more flexibility and to make use of more options, the -mon command-line option should be used. For instance, the following example @@ -34,7 +34,7 @@ creates one HMP instance (human monitor) on stdio and one QMP instance on localhost port 4444: $ qemu [...] -chardev stdio,id=mon0 -mon chardev=mon0,mode=readline \ - -chardev socket,id=mon1,host=localhost,port=4444,server,nowait \ + -chardev socket,id=mon1,host=localhost,port=4444,server=on,wait=off \ -mon chardev=mon1,mode=control,pretty=on Please, refer to QEMU's manpage for more information. diff --git a/docs/system/cpu-hotplug.rst b/docs/system/cpu-hotplug.rst index d0b0640..bd06636 100644 --- a/docs/system/cpu-hotplug.rst +++ b/docs/system/cpu-hotplug.rst @@ -14,7 +14,7 @@ vCPU hotplug $ qemu-system-x86_64 -display none -no-user-config -m 2048 \ -nodefaults -monitor stdio -machine pc,accel=kvm,usb=off \ -smp 1,maxcpus=2 -cpu IvyBridge-IBRS \ - -qmp unix:/tmp/qmp-sock,server,nowait + -qmp unix:/tmp/qmp-sock,server=on,wait=off (2) Run 'qmp-shell' (located in the source tree, under: "scripts/qmp/) to connect to the just-launched QEMU:: diff --git a/docs/system/cpu-models-x86.rst.inc b/docs/system/cpu-models-x86.rst.inc index 9a23278..867c821 100644 --- a/docs/system/cpu-models-x86.rst.inc +++ b/docs/system/cpu-models-x86.rst.inc @@ -364,7 +364,7 @@ Host passthrough with feature customization: .. parsed-literal:: - |qemu_system| -cpu host,-vmx,... + |qemu_system| -cpu host,vmx=off,... Named CPU models: @@ -376,7 +376,7 @@ Named CPU models with feature customization: .. parsed-literal:: - |qemu_system| -cpu Westmere,+pcid,... + |qemu_system| -cpu Westmere,pcid=on,... Libvirt guest XML ^^^^^^^^^^^^^^^^^ diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index 2fcac78..561c916 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -146,6 +146,13 @@ library enabled as a cryptography provider. Neither the ``nettle`` library, or the built-in cryptography provider are supported on FIPS enabled hosts. +``-writeconfig`` (since 6.0) +''''''''''''''''''''''''''''' + +The ``-writeconfig`` option is not able to serialize the entire contents +of the QEMU command line. It is thus considered a failed experiment +and deprecated, with no current replacement. + QEMU Machine Protocol (QMP) commands ------------------------------------ diff --git a/docs/system/s390x/3270.rst b/docs/system/s390x/3270.rst index 0554a70..0e173b3 100644 --- a/docs/system/s390x/3270.rst +++ b/docs/system/s390x/3270.rst @@ -24,7 +24,7 @@ Example configuration * Add a ``tn3270`` chardev and a ``x-terminal3270`` to the QEMU command line:: - -chardev socket,id=ch0,host=0.0.0.0,port=2300,nowait,server,tn3270 + -chardev socket,id=ch0,host=0.0.0.0,port=2300,wait=off,server=on,tn3270=on -device x-terminal3270,chardev=ch0,devno=fe.0.000a,id=terminal0 * Start the guest. In the guest, use ``chccwdev -e 0.0.000a`` to enable diff --git a/docs/system/target-avr.rst b/docs/system/target-avr.rst index 25ab46e..03d5ab5 100644 --- a/docs/system/target-avr.rst +++ b/docs/system/target-avr.rst @@ -24,7 +24,7 @@ AVR cpu - Continuous non interrupted execution with serial output into telnet window:: qemu-system-avr -M mega2560 -bios demo.elf -nographic \ - -serial tcp::5678,server,nowait + -serial tcp::5678,server=on,wait=off and then in another shell:: diff --git a/docs/system/vnc-security.rst b/docs/system/vnc-security.rst index ebca656..830f6ac 100644 --- a/docs/system/vnc-security.rst +++ b/docs/system/vnc-security.rst @@ -44,7 +44,7 @@ the password all clients will be rejected. .. parsed-literal:: - |qemu_system| [...OPTIONS...] -vnc :1,password -monitor stdio + |qemu_system| [...OPTIONS...] -vnc :1,password=on -monitor stdio (qemu) change vnc password Password: ******** (qemu) @@ -104,7 +104,7 @@ authentication to provide two layers of authentication for clients. |qemu_system| [...OPTIONS...] \ -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server,verify-peer=on \ - -vnc :1,tls-creds=tls0,password -monitor stdio + -vnc :1,tls-creds=tls0,password=on -monitor stdio (qemu) change vnc password Password: ******** (qemu) @@ -128,7 +128,7 @@ can be launched with: .. parsed-literal:: - |qemu_system| [...OPTIONS...] -vnc :1,sasl -monitor stdio + |qemu_system| [...OPTIONS...] -vnc :1,sasl=on -monitor stdio .. _vnc_005fsec_005fcertificate_005fsasl: @@ -146,7 +146,7 @@ x509 options: |qemu_system| [...OPTIONS...] \ -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server,verify-peer=on \ - -vnc :1,tls-creds=tls0,sasl -monitor stdio + -vnc :1,tls-creds=tls0,sasl=on -monitor stdio .. _vnc_005fsetup_005fsasl: diff --git a/docs/tools/qemu-storage-daemon.rst b/docs/tools/qemu-storage-daemon.rst index f63627e..c05b3d3 100644 --- a/docs/tools/qemu-storage-daemon.rst +++ b/docs/tools/qemu-storage-daemon.rst @@ -69,7 +69,7 @@ Standard options: a description of character device properties. A common character device definition configures a UNIX domain socket:: - --chardev socket,id=char1,path=/tmp/qmp.sock,server,nowait + --chardev socket,id=char1,path=/tmp/qmp.sock,server=on,wait=off .. option:: --export [type=]nbd,id=<id>,node-name=<node-name>[,name=<export-name>][,writable=on|off][,bitmap=<name>] --export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,addr.type=unix,addr.path=<socket-path>[,writable=on|off][,logical-block-size=<block-size>][,num-queues=<num-queues>] @@ -124,7 +124,7 @@ Launch the daemon with QMP monitor socket ``qmp.sock`` so clients can execute QMP commands:: $ qemu-storage-daemon \ - --chardev socket,path=qmp.sock,server,nowait,id=char1 \ + --chardev socket,path=qmp.sock,server=on,wait=off,id=char1 \ --monitor chardev=char1 Export raw image file ``disk.img`` over NBD UNIX domain socket ``nbd.sock``:: @@ -3505,7 +3505,7 @@ int gdbserver_start(const char *device) if (strstart(device, "tcp:", NULL)) { /* enforce required TCP attributes */ snprintf(gdbstub_device_name, sizeof(gdbstub_device_name), - "%s,nowait,nodelay,server", device); + "%s,wait=off,delay=off,server=on", device); device = gdbstub_device_name; } #ifndef _WIN32 diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c index 2ce96dc..4d7c2ca 100644 --- a/hw/scsi/esp-pci.c +++ b/hw/scsi/esp-pci.c @@ -329,13 +329,12 @@ static const VMStateDescription vmstate_esp_pci_scsi = { } }; -static void esp_pci_command_complete(SCSIRequest *req, uint32_t status, - size_t resid) +static void esp_pci_command_complete(SCSIRequest *req, size_t resid) { ESPState *s = req->hba_private; PCIESPState *pci = container_of(s, PCIESPState, esp); - esp_command_complete(req, status, resid); + esp_command_complete(req, resid); pci->dma_regs[DMA_WBC] = 0; pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE; } diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index b84e0fe..93d9c9c 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -485,8 +485,7 @@ static void esp_report_command_complete(ESPState *s, uint32_t status) } } -void esp_command_complete(SCSIRequest *req, uint32_t status, - size_t resid) +void esp_command_complete(SCSIRequest *req, size_t resid) { ESPState *s = req->hba_private; @@ -495,11 +494,11 @@ void esp_command_complete(SCSIRequest *req, uint32_t status, * interrupt has been handled. */ trace_esp_command_complete_deferred(); - s->deferred_status = status; + s->deferred_status = req->status; s->deferred_complete = true; return; } - esp_report_command_complete(s, status); + esp_report_command_complete(s, req->status); } void esp_transfer_data(SCSIRequest *req, uint32_t len) diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 7d13c7d..a4e58580 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -787,14 +787,14 @@ static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len) } /* Callback to indicate that the SCSI layer has completed a command. */ -static void lsi_command_complete(SCSIRequest *req, uint32_t status, size_t resid) +static void lsi_command_complete(SCSIRequest *req, size_t resid) { LSIState *s = LSI53C895A(req->bus->qbus.parent); int out; out = (s->sstat1 & PHASE_MASK) == PHASE_DO; - trace_lsi_command_complete(status); - s->status = status; + trace_lsi_command_complete(req->status); + s->status = req->status; s->command_complete = 2; if (s->waiting && s->dbc != 0) { /* Raise phase mismatch for short transfers. */ diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 5bfc92f..8f2389d 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -1852,13 +1852,12 @@ static void megasas_xfer_complete(SCSIRequest *req, uint32_t len) } } -static void megasas_command_complete(SCSIRequest *req, uint32_t status, - size_t resid) +static void megasas_command_complete(SCSIRequest *req, size_t resid) { MegasasCmd *cmd = req->hba_private; uint8_t cmd_status = MFI_STAT_OK; - trace_megasas_command_complete(cmd->index, status, resid); + trace_megasas_command_complete(cmd->index, req->status, resid); if (req->io_canceled) { return; @@ -1873,7 +1872,6 @@ static void megasas_command_complete(SCSIRequest *req, uint32_t status, return; } } else { - req->status = status; trace_megasas_scsi_complete(cmd->index, req->status, cmd->iov_size, req->cmd.xfer); if (req->status != GOOD) { diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c index f866165..7416e78 100644 --- a/hw/scsi/mptsas.c +++ b/hw/scsi/mptsas.c @@ -1133,7 +1133,7 @@ static QEMUSGList *mptsas_get_sg_list(SCSIRequest *sreq) } static void mptsas_command_complete(SCSIRequest *sreq, - uint32_t status, size_t resid) + size_t resid) { MPTSASRequest *req = sreq->hba_private; MPTSASState *s = req->dev; @@ -1143,7 +1143,8 @@ static void mptsas_command_complete(SCSIRequest *sreq, hwaddr sense_buffer_addr = req->dev->sense_buffer_high_addr | req->scsi_io.SenseBufferLowAddr; - trace_mptsas_command_complete(s, req->scsi_io.MsgContext, status, resid); + trace_mptsas_command_complete(s, req->scsi_io.MsgContext, + sreq->status, resid); sense_len = scsi_req_get_sense(sreq, sense_buf, SCSI_SENSE_BUF_SIZE); if (sense_len > 0) { diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index c349fb7..dc4141e 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -1483,7 +1483,7 @@ void scsi_req_complete(SCSIRequest *req, int status) scsi_req_ref(req); scsi_req_dequeue(req); - req->bus->info->complete(req, req->status, req->resid); + req->bus->info->complete(req, req->resid); /* Cancelled requests might end up being completed instead of cancelled */ notifier_list_notify(&req->cancel_notifiers, req); diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index ed52fcd..a5a58d7 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -111,8 +111,6 @@ struct SCSIDiskState { uint16_t rotation_rate; }; -static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed); - static void scsi_free_request(SCSIRequest *req) { SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); @@ -182,6 +180,78 @@ static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req) qemu_iovec_init_external(&r->qiov, &r->iov, 1); } +/* + * scsi_handle_rw_error has two return values. False means that the error + * must be ignored, true means that the error has been processed and the + * caller should not do anything else for this request. Note that + * scsi_handle_rw_error always manages its reference counts, independent + * of the return value. + */ +static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed) +{ + bool is_read = (r->req.cmd.mode == SCSI_XFER_FROM_DEV); + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s)); + SCSISense sense = SENSE_CODE(NO_SENSE); + int error = 0; + bool req_has_sense = false; + BlockErrorAction action; + int status; + + if (ret < 0) { + status = scsi_sense_from_errno(-ret, &sense); + error = -ret; + } else { + /* A passthrough command has completed with nonzero status. */ + status = ret; + if (status == CHECK_CONDITION) { + req_has_sense = true; + error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense)); + } else { + error = EINVAL; + } + } + + /* + * Check whether the error has to be handled by the guest or should + * rather follow the rerror=/werror= settings. Guest-handled errors + * are usually retried immediately, so do not post them to QMP and + * do not account them as failed I/O. + */ + if (req_has_sense && + scsi_sense_buf_is_guest_recoverable(r->req.sense, sizeof(r->req.sense))) { + action = BLOCK_ERROR_ACTION_REPORT; + acct_failed = false; + } else { + action = blk_get_error_action(s->qdev.conf.blk, is_read, error); + blk_error_action(s->qdev.conf.blk, action, is_read, error); + } + + switch (action) { + case BLOCK_ERROR_ACTION_REPORT: + if (acct_failed) { + block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct); + } + if (req_has_sense) { + sdc->update_sense(&r->req); + } else if (status == CHECK_CONDITION) { + scsi_req_build_sense(&r->req, sense); + } + scsi_req_complete(&r->req, status); + return true; + + case BLOCK_ERROR_ACTION_IGNORE: + return false; + + case BLOCK_ERROR_ACTION_STOP: + scsi_req_retry(&r->req); + return true; + + default: + g_assert_not_reached(); + } +} + static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed) { if (r->req.io_canceled) { @@ -189,8 +259,10 @@ static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed) return true; } - if (ret < 0 || (r->status && *r->status)) { - return scsi_handle_rw_error(r, -ret, acct_failed); + if (ret < 0) { + return scsi_handle_rw_error(r, ret, acct_failed); + } else if (r->status && *r->status) { + return scsi_handle_rw_error(r, *r->status, acct_failed); } return false; @@ -428,89 +500,6 @@ static void scsi_read_data(SCSIRequest *req) } } -/* - * scsi_handle_rw_error has two return values. False means that the error - * must be ignored, true means that the error has been processed and the - * caller should not do anything else for this request. Note that - * scsi_handle_rw_error always manages its reference counts, independent - * of the return value. - */ -static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed) -{ - bool is_read = (r->req.cmd.mode == SCSI_XFER_FROM_DEV); - SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s)); - BlockErrorAction action = blk_get_error_action(s->qdev.conf.blk, - is_read, error); - - if (action == BLOCK_ERROR_ACTION_REPORT) { - if (acct_failed) { - block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct); - } - switch (error) { - case 0: - /* A passthrough command has run and has produced sense data; check - * whether the error has to be handled by the guest or should rather - * pause the host. - */ - assert(r->status && *r->status); - if (scsi_sense_buf_is_guest_recoverable(r->req.sense, sizeof(r->req.sense))) { - /* These errors are handled by guest. */ - sdc->update_sense(&r->req); - scsi_req_complete(&r->req, *r->status); - return true; - } - error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense)); - break; -#ifdef CONFIG_LINUX - /* These errno mapping are specific to Linux. For more information: - * - scsi_decide_disposition in drivers/scsi/scsi_error.c - * - scsi_result_to_blk_status in drivers/scsi/scsi_lib.c - * - blk_errors[] in block/blk-core.c - */ - case EBADE: - /* DID_NEXUS_FAILURE -> BLK_STS_NEXUS. */ - scsi_req_complete(&r->req, RESERVATION_CONFLICT); - break; - case ENODATA: - /* DID_MEDIUM_ERROR -> BLK_STS_MEDIUM. */ - scsi_check_condition(r, SENSE_CODE(READ_ERROR)); - break; - case EREMOTEIO: - /* DID_TARGET_FAILURE -> BLK_STS_TARGET. */ - scsi_req_complete(&r->req, HARDWARE_ERROR); - break; -#endif - case ENOMEDIUM: - scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); - break; - case ENOMEM: - scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE)); - break; - case EINVAL: - scsi_check_condition(r, SENSE_CODE(INVALID_FIELD)); - break; - case ENOSPC: - scsi_check_condition(r, SENSE_CODE(SPACE_ALLOC_FAILED)); - break; - default: - scsi_check_condition(r, SENSE_CODE(IO_ERROR)); - break; - } - } - - blk_error_action(s->qdev.conf.blk, action, is_read, error); - if (action == BLOCK_ERROR_ACTION_IGNORE) { - scsi_req_complete(&r->req, 0); - return true; - } - - if (action == BLOCK_ERROR_ACTION_STOP) { - scsi_req_retry(&r->req); - } - return true; -} - static void scsi_write_complete_noio(SCSIDiskReq *r, int ret) { uint32_t n; @@ -2624,7 +2613,7 @@ static int get_device_type(SCSIDiskState *s) cmd[4] = sizeof(buf); ret = scsi_SG_IO_FROM_DEV(s->qdev.conf.blk, cmd, sizeof(cmd), - buf, sizeof(buf)); + buf, sizeof(buf), s->qdev.io_timeout); if (ret < 0) { return -1; } @@ -2785,10 +2774,11 @@ static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req, /* The rest is as in scsi-generic.c. */ io_header->mx_sb_len = sizeof(r->req.sense); io_header->sbp = r->req.sense; - io_header->timeout = UINT_MAX; + io_header->timeout = s->qdev.io_timeout * 1000; io_header->usr_ptr = r; io_header->flags |= SG_FLAG_DIRECT_IO; - + trace_scsi_disk_aio_sgio_command(r->req.tag, req->cdb[0], lba, + nb_logical_blocks, io_header->timeout); aiocb = blk_aio_ioctl(s->qdev.conf.blk, SG_IO, io_header, cb, opaque); assert(aiocb != NULL); return aiocb; @@ -3103,6 +3093,8 @@ static Property scsi_block_properties[] = { DEFAULT_MAX_IO_SIZE), DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, -1), + DEFINE_PROP_UINT32("io_timeout", SCSIDiskState, qdev.io_timeout, + DEFAULT_IO_TIMEOUT), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index ab22014..cf7e11c 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -115,6 +115,8 @@ static int execute_command(BlockBackend *blk, SCSIGenericReq *r, int direction, BlockCompletionFunc *complete) { + SCSIDevice *s = r->req.dev; + r->io_header.interface_id = 'S'; r->io_header.dxfer_direction = direction; r->io_header.dxferp = r->buf; @@ -123,10 +125,12 @@ static int execute_command(BlockBackend *blk, r->io_header.cmd_len = r->req.cmd.len; r->io_header.mx_sb_len = sizeof(r->req.sense); r->io_header.sbp = r->req.sense; - r->io_header.timeout = MAX_UINT; + r->io_header.timeout = s->io_timeout * 1000; r->io_header.usr_ptr = r; r->io_header.flags |= SG_FLAG_DIRECT_IO; + trace_scsi_generic_aio_sgio_command(r->req.tag, r->req.cmd.buf[0], + r->io_header.timeout); r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r); if (r->req.aiocb == NULL) { return -EIO; @@ -506,7 +510,7 @@ static int read_naa_id(const uint8_t *p, uint64_t *p_wwn) } int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size, - uint8_t *buf, uint8_t buf_size) + uint8_t *buf, uint8_t buf_size, uint32_t timeout) { sg_io_hdr_t io_header; uint8_t sensebuf[8]; @@ -521,10 +525,14 @@ int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size, io_header.cmd_len = cmd_size; io_header.mx_sb_len = sizeof(sensebuf); io_header.sbp = sensebuf; - io_header.timeout = 6000; /* XXX */ + io_header.timeout = timeout * 1000; + trace_scsi_generic_ioctl_sgio_command(cmd[0], io_header.timeout); ret = blk_ioctl(blk, SG_IO, &io_header); - if (ret < 0 || io_header.driver_status || io_header.host_status) { + if (ret < 0 || io_header.status || + io_header.driver_status || io_header.host_status) { + trace_scsi_generic_ioctl_sgio_done(cmd[0], ret, io_header.status, + io_header.host_status); return -1; } return 0; @@ -551,7 +559,7 @@ static void scsi_generic_set_vpd_bl_emulation(SCSIDevice *s) cmd[4] = sizeof(buf); ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd), - buf, sizeof(buf)); + buf, sizeof(buf), s->io_timeout); if (ret < 0) { /* * Do not assume anything if we can't retrieve the @@ -587,7 +595,7 @@ static void scsi_generic_read_device_identification(SCSIDevice *s) cmd[4] = sizeof(buf); ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd), - buf, sizeof(buf)); + buf, sizeof(buf), s->io_timeout); if (ret < 0) { return; } @@ -638,7 +646,7 @@ static int get_stream_blocksize(BlockBackend *blk) cmd[0] = MODE_SENSE; cmd[4] = sizeof(buf); - ret = scsi_SG_IO_FROM_DEV(blk, cmd, sizeof(cmd), buf, sizeof(buf)); + ret = scsi_SG_IO_FROM_DEV(blk, cmd, sizeof(cmd), buf, sizeof(buf), 6); if (ret < 0) { return -1; } @@ -665,7 +673,8 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp) return; } - if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) { + if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC && + blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_REPORT) { error_setg(errp, "Device doesn't support drive option werror"); return; } @@ -728,6 +737,7 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp) /* Only used by scsi-block, but initialize it nevertheless to be clean. */ s->default_scsi_version = -1; + s->io_timeout = DEFAULT_IO_TIMEOUT; scsi_generic_read_device_inquiry(s); } @@ -751,6 +761,8 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun, static Property scsi_generic_properties[] = { DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk), DEFINE_PROP_BOOL("share-rw", SCSIDevice, conf.share_rw, false), + DEFINE_PROP_UINT32("io_timeout", SCSIDevice, io_timeout, + DEFAULT_IO_TIMEOUT), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c index 4aa0224..ca5c13c 100644 --- a/hw/scsi/spapr_vscsi.c +++ b/hw/scsi/spapr_vscsi.c @@ -551,19 +551,19 @@ static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len) } /* Callback to indicate that the SCSI layer has completed a transfer. */ -static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, size_t resid) +static void vscsi_command_complete(SCSIRequest *sreq, size_t resid) { VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(sreq->bus->qbus.parent); vscsi_req *req = sreq->hba_private; int32_t res_in = 0, res_out = 0; - trace_spapr_vscsi_command_complete(sreq->tag, status, req); + trace_spapr_vscsi_command_complete(sreq->tag, sreq->status, req); if (req == NULL) { fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", sreq->tag); return; } - if (status == CHECK_CONDITION) { + if (sreq->status == CHECK_CONDITION) { req->senselen = scsi_req_get_sense(req->sreq, req->sense, sizeof(req->sense)); trace_spapr_vscsi_command_complete_sense_data1(req->senselen, @@ -574,8 +574,8 @@ static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, size_t re req->sense[12], req->sense[13], req->sense[14], req->sense[15]); } - trace_spapr_vscsi_command_complete_status(status); - if (status == 0) { + trace_spapr_vscsi_command_complete_status(sreq->status); + if (sreq->status == 0) { /* We handle overflows, not underflows for normal commands, * but hopefully nobody cares */ @@ -585,7 +585,7 @@ static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, size_t re res_in = req->data_len; } } - vscsi_send_rsp(s, req, status, res_in, res_out); + vscsi_send_rsp(s, req, sreq->status, res_in, res_out); vscsi_put_req(req); } diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events index 0e0aa98..9788661 100644 --- a/hw/scsi/trace-events +++ b/hw/scsi/trace-events @@ -331,6 +331,7 @@ scsi_disk_emulate_command_UNKNOWN(int cmd, const char *name) "Unknown SCSI comma scsi_disk_dma_command_READ(uint64_t lba, uint32_t len) "Read (sector %" PRId64 ", count %u)" scsi_disk_dma_command_WRITE(const char *cmd, uint64_t lba, int len) "Write %s(sector %" PRId64 ", count %u)" scsi_disk_new_request(uint32_t lun, uint32_t tag, const char *line) "Command: lun=%d tag=0x%x data=%s" +scsi_disk_aio_sgio_command(uint32_t tag, uint8_t cmd, uint64_t lba, int len, uint32_t timeout) "disk aio sgio: tag=0x%x cmd=0x%x (sector %" PRId64 ", count %d) timeout=%u" # scsi-generic.c scsi_generic_command_complete_noio(void *req, uint32_t tag, int statuc) "Command complete %p tag=0x%x status=%d" @@ -342,3 +343,6 @@ scsi_generic_write_data(uint32_t tag) "scsi_write_data tag=0x%x" scsi_generic_send_command(const char *line) "Command: data=%s" scsi_generic_realize_type(int type) "device type %d" scsi_generic_realize_blocksize(int blocksize) "block size %d" +scsi_generic_aio_sgio_command(uint32_t tag, uint8_t cmd, uint32_t timeout) "generic aio sgio: tag=0x%x cmd=0x%x timeout=%u" +scsi_generic_ioctl_sgio_command(uint8_t cmd, uint32_t timeout) "generic ioctl sgio: cmd=0x%x timeout=%u" +scsi_generic_ioctl_sgio_done(uint8_t cmd, int ret, uint8_t status, uint8_t host_status) "generic ioctl sgio: cmd=0x%x ret=%d status=0x%x host_status=0x%x" diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 2c83a0a..4ad8793 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -52,12 +52,14 @@ void virtio_scsi_dataplane_setup(VirtIOSCSI *s, Error **errp) static bool virtio_scsi_data_plane_handle_cmd(VirtIODevice *vdev, VirtQueue *vq) { - bool progress; + bool progress = false; VirtIOSCSI *s = VIRTIO_SCSI(vdev); virtio_scsi_acquire(s); - assert(s->ctx && s->dataplane_started); - progress = virtio_scsi_handle_cmd_vq(s, vq); + if (!s->dataplane_fenced) { + assert(s->ctx && s->dataplane_started); + progress = virtio_scsi_handle_cmd_vq(s, vq); + } virtio_scsi_release(s); return progress; } @@ -65,12 +67,14 @@ static bool virtio_scsi_data_plane_handle_cmd(VirtIODevice *vdev, static bool virtio_scsi_data_plane_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) { - bool progress; + bool progress = false; VirtIOSCSI *s = VIRTIO_SCSI(vdev); virtio_scsi_acquire(s); - assert(s->ctx && s->dataplane_started); - progress = virtio_scsi_handle_ctrl_vq(s, vq); + if (!s->dataplane_fenced) { + assert(s->ctx && s->dataplane_started); + progress = virtio_scsi_handle_ctrl_vq(s, vq); + } virtio_scsi_release(s); return progress; } @@ -78,12 +82,14 @@ static bool virtio_scsi_data_plane_handle_ctrl(VirtIODevice *vdev, static bool virtio_scsi_data_plane_handle_event(VirtIODevice *vdev, VirtQueue *vq) { - bool progress; + bool progress = false; VirtIOSCSI *s = VIRTIO_SCSI(vdev); virtio_scsi_acquire(s); - assert(s->ctx && s->dataplane_started); - progress = virtio_scsi_handle_event_vq(s, vq); + if (!s->dataplane_fenced) { + assert(s->ctx && s->dataplane_started); + progress = virtio_scsi_handle_event_vq(s, vq); + } virtio_scsi_release(s); return progress; } diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 99ff261..358c0e7 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -500,8 +500,7 @@ static void virtio_scsi_complete_cmd_req(VirtIOSCSIReq *req) virtio_scsi_complete_req(req); } -static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status, - size_t resid) +static void virtio_scsi_command_complete(SCSIRequest *r, size_t resid) { VirtIOSCSIReq *req = r->hba_private; uint8_t sense[SCSI_SENSE_BUF_SIZE]; @@ -513,7 +512,7 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status, } req->resp.cmd.response = VIRTIO_SCSI_S_OK; - req->resp.cmd.status = status; + req->resp.cmd.status = r->status; if (req->resp.cmd.status == GOOD) { req->resp.cmd.resid = virtio_tswap32(vdev, resid); } else { diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index a63d25d..0da378e 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -511,7 +511,7 @@ pvscsi_write_sense(PVSCSIRequest *r, uint8_t *sense, int len) } static void -pvscsi_command_complete(SCSIRequest *req, uint32_t status, size_t resid) +pvscsi_command_complete(SCSIRequest *req, size_t resid) { PVSCSIRequest *pvscsi_req = req->hba_private; PVSCSIState *s; @@ -528,7 +528,7 @@ pvscsi_command_complete(SCSIRequest *req, uint32_t status, size_t resid) pvscsi_req->cmp.hostStatus = BTSTAT_DATARUN; } - pvscsi_req->cmp.scsiStatus = status; + pvscsi_req->cmp.scsiStatus = req->status; if (pvscsi_req->cmp.scsiStatus == CHECK_CONDITION) { uint8_t sense[SCSI_SENSE_BUF_SIZE]; int sense_len = diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index c49e8b8..a5f76fc 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -277,17 +277,17 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len) } } -static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t resid) +static void usb_msd_command_complete(SCSIRequest *req, size_t resid) { MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); USBPacket *p = s->packet; - trace_usb_msd_cmd_complete(status, req->tag); + trace_usb_msd_cmd_complete(req->status, req->tag); s->csw.sig = cpu_to_le32(0x53425355); s->csw.tag = cpu_to_le32(req->tag); s->csw.residue = cpu_to_le32(s->data_len); - s->csw.status = status != 0; + s->csw.status = req->status != 0; if (s->packet) { if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) { diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index a51402b..d2bd85d 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -598,17 +598,16 @@ static void usb_uas_scsi_transfer_data(SCSIRequest *r, uint32_t len) } } -static void usb_uas_scsi_command_complete(SCSIRequest *r, - uint32_t status, size_t resid) +static void usb_uas_scsi_command_complete(SCSIRequest *r, size_t resid) { UASRequest *req = r->hba_private; - trace_usb_uas_scsi_complete(req->uas->dev.addr, req->tag, status, resid); + trace_usb_uas_scsi_complete(req->uas->dev.addr, req->tag, r->status, resid); req->complete = true; if (req->data) { usb_uas_complete_data_packet(req); } - usb_uas_queue_sense(req, status); + usb_uas_queue_sense(req, r->status); scsi_req_unref(req->req); } diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h index 60cc304..d8a6263 100644 --- a/include/hw/scsi/esp.h +++ b/include/hw/scsi/esp.h @@ -151,7 +151,7 @@ struct SysBusESPState { void esp_dma_enable(ESPState *s, int irq, int level); void esp_request_cancelled(SCSIRequest *req); -void esp_command_complete(SCSIRequest *req, uint32_t status, size_t resid); +void esp_command_complete(SCSIRequest *req, size_t resid); void esp_transfer_data(SCSIRequest *req, uint32_t len); void esp_hard_reset(ESPState *s); uint64_t esp_reg_read(ESPState *s, uint32_t saddr); diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 09fa5c9..5d992e6 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -18,6 +18,7 @@ typedef struct SCSIReqOps SCSIReqOps; #define SCSI_SENSE_BUF_SIZE_OLD 96 #define SCSI_SENSE_BUF_SIZE 252 +#define DEFAULT_IO_TIMEOUT 30 struct SCSIRequest { SCSIBus *bus; @@ -84,6 +85,7 @@ struct SCSIDevice uint64_t port_wwn; int scsi_version; int default_scsi_version; + uint32_t io_timeout; bool needs_vpd_bl_emulation; bool hba_supports_iothread; }; @@ -121,7 +123,7 @@ struct SCSIBusInfo { int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, void *hba_private); void (*transfer_data)(SCSIRequest *req, uint32_t arg); - void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid); + void (*complete)(SCSIRequest *req, size_t resid); void (*cancel)(SCSIRequest *req); void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense); QEMUSGList *(*get_sg_list)(SCSIRequest *req); @@ -188,7 +190,7 @@ void scsi_device_unit_attention_reported(SCSIDevice *dev); void scsi_generic_read_device_inquiry(SCSIDevice *dev); int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed); int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size, - uint8_t *buf, uint8_t buf_size); + uint8_t *buf, uint8_t buf_size, uint32_t timeout); SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun); SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int target, int lun); diff --git a/include/scsi/utils.h b/include/scsi/utils.h index 096489c..ff7c709 100644 --- a/include/scsi/utils.h +++ b/include/scsi/utils.h @@ -135,4 +135,6 @@ int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr, SCSISense *sense); #endif +int scsi_sense_from_errno(int errno_value, SCSISense *sense); + #endif diff --git a/meson.build b/meson.build index f3db83e..07bc231 100644 --- a/meson.build +++ b/meson.build @@ -157,6 +157,11 @@ if targetos != 'linux' and get_option('mpath').enabled() error('Multipath is supported only on Linux') endif +if targetos != 'linux' and get_option('multiprocess').enabled() + error('Multiprocess QEMU is supported only on Linux') +endif +multiprocess_allowed = targetos == 'linux' and not get_option('multiprocess').disabled() + m = cc.find_library('m', required: false) util = cc.find_library('util', required: false) winmm = [] @@ -1228,7 +1233,7 @@ host_kconfig = \ (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \ ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \ ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \ - ('CONFIG_MULTIPROCESS_ALLOWED' in config_host ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ] @@ -2224,7 +2229,7 @@ foreach target : target_dirs endif emulator = executable(exe_name, exe['sources'], - install: not exe_sign, + install: true, c_args: c_args, dependencies: arch_deps + deps + exe['dependencies'], objects: lib.extract_all_objects(recursive: true), @@ -2235,8 +2240,6 @@ foreach target : target_dirs if exe_sign emulators += {exe['name'] : custom_target(exe['name'], - install: true, - install_dir: get_option('bindir'), depends: emulator, output: exe['name'], command: [ @@ -2246,6 +2249,11 @@ foreach target : target_dirs meson.current_source_dir() / 'accel/hvf/entitlements.plist' ]) } + + meson.add_install_script('scripts/entitlement.sh', '--install', + get_option('bindir') / exe_name, + get_option('bindir') / exe['name'], + meson.current_source_dir() / 'accel/hvf/entitlements.plist') else emulators += {exe['name']: emulator} endif @@ -2553,6 +2561,7 @@ endif summary_info += {'target list': ' '.join(target_dirs)} if have_system summary_info += {'default devices': get_option('default_devices')} + summary_info += {'out of process emulation': multiprocess_allowed} endif summary(summary_info, bool_yn: true, section: 'Targets and accelerators') @@ -2673,7 +2682,6 @@ summary_info += {'libpmem support': config_host.has_key('CONFIG_LIBPMEM')} summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')} summary_info += {'libudev': libudev.found()} summary_info += {'FUSE lseek': fuse_lseek.found()} -summary_info += {'Multiprocess QEMU': config_host.has_key('CONFIG_MULTIPROCESS_ALLOWED')} summary(summary_info, bool_yn: true, section: 'Dependencies') if not supported_cpus.contains(cpu) diff --git a/meson_options.txt b/meson_options.txt index 675a9c5..9734019 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -45,6 +45,8 @@ option('cfi', type: 'boolean', value: 'false', description: 'Control-Flow Integrity (CFI)') option('cfi_debug', type: 'boolean', value: 'false', description: 'Verbose errors in case of CFI violation') +option('multiprocess', type: 'feature', value: 'auto', + description: 'Out of process device emulation support') option('attr', type : 'feature', value : 'auto', description: 'attr/xattr support') diff --git a/qapi/char.json b/qapi/char.json index 58338ed..6413970 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -47,12 +47,12 @@ # "return": [ # { # "label": "charchannel0", -# "filename": "unix:/var/lib/libvirt/qemu/seabios.rhel6.agent,server", +# "filename": "unix:/var/lib/libvirt/qemu/seabios.rhel6.agent,server=on", # "frontend-open": false # }, # { # "label": "charmonitor", -# "filename": "unix:/var/lib/libvirt/qemu/seabios.rhel6.monitor,server", +# "filename": "unix:/var/lib/libvirt/qemu/seabios.rhel6.monitor,server=on", # "frontend-open": true # }, # { diff --git a/qemu-options.hx b/qemu-options.hx index 6c34c70..252db93 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1894,16 +1894,17 @@ DEF("spice", HAS_ARG, QEMU_OPTION_spice, "-spice [port=port][,tls-port=secured-port][,x509-dir=<dir>]\n" " [,x509-key-file=<file>][,x509-key-password=<file>]\n" " [,x509-cert-file=<file>][,x509-cacert-file=<file>]\n" - " [,x509-dh-key-file=<file>][,addr=addr][,ipv4|ipv6|unix]\n" + " [,x509-dh-key-file=<file>][,addr=addr]\n" + " [,ipv4=on|off][,ipv6=on|off][,unix=on|off]\n" " [,tls-ciphers=<list>]\n" " [,tls-channel=[main|display|cursor|inputs|record|playback]]\n" " [,plaintext-channel=[main|display|cursor|inputs|record|playback]]\n" - " [,sasl][,password=<secret>][,disable-ticketing]\n" + " [,sasl=on|off][,password=<secret>][,disable-ticketing=on|off]\n" " [,image-compression=[auto_glz|auto_lz|quic|glz|lz|off]]\n" " [,jpeg-wan-compression=[auto|never|always]]\n" " [,zlib-glz-wan-compression=[auto|never|always]]\n" - " [,streaming-video=[off|all|filter]][,disable-copy-paste]\n" - " [,disable-agent-file-xfer][,agent-mouse=[on|off]]\n" + " [,streaming-video=[off|all|filter]][,disable-copy-paste=on|off]\n" + " [,disable-agent-file-xfer=on|off][,agent-mouse=[on|off]]\n" " [,playback-compression=[on|off]][,seamless-migration=[on|off]]\n" " [,gl=[on|off]][,rendernode=<file>]\n" " enable spice\n" @@ -1920,13 +1921,13 @@ SRST Set the IP address spice is listening on. Default is any address. - ``ipv4``; \ ``ipv6``; \ ``unix`` + ``ipv4=on|off``; \ ``ipv6=on|off``; \ ``unix=on|off`` Force using the specified IP version. ``password=<secret>`` Set the password you need to authenticate. - ``sasl`` + ``sasl=on|off`` Require that the client use SASL to authenticate with the spice. The exact choice of authentication method used is controlled from the system / user's SASL configuration file for the 'qemu' @@ -1940,13 +1941,13 @@ SRST data encryption preventing compromise of authentication credentials. - ``disable-ticketing`` + ``disable-ticketing=on|off`` Allow client connects without authentication. - ``disable-copy-paste`` + ``disable-copy-paste=on|off`` Disable copy paste between the client and the guest. - ``disable-agent-file-xfer`` + ``disable-agent-file-xfer=on|off`` Disable spice-vdagent based file-xfer between the client and the guest. @@ -2122,13 +2123,13 @@ SRST Following the display value there may be one or more option flags separated by commas. Valid options are - ``reverse`` + ``reverse=on|off`` Connect to a listening VNC client via a "reverse" connection. The client is specified by the display. For reverse network connections (host:d,``reverse``), the d argument is a TCP port number, not a display number. - ``websocket`` + ``websocket=on|off`` Opens an additional TCP listening port dedicated to VNC Websocket connections. If a bare websocket option is given, the Websocket port is 5700+display. An alternative port can be @@ -2142,7 +2143,7 @@ SRST runs in unencrypted mode. If TLS credentials are provided, the websocket connection requires encrypted client connections. - ``password`` + ``password=on|off`` Require that password based authentication is used for client connections. @@ -2179,7 +2180,7 @@ SRST on the fly while the VNC server is active. If missing, it will default to denying access. - ``sasl`` + ``sasl=on|off`` Require that the client use SASL to authenticate with the VNC server. The exact choice of authentication method used is controlled from the system / user's SASL configuration file for @@ -2202,7 +2203,7 @@ SRST fly while the VNC server is active. If missing, it will default to denying access. - ``acl`` + ``acl=on|off`` Legacy method for enabling authorization of clients against the x509 distinguished name and SASL username. It results in the creation of two ``authz-list`` objects with IDs of @@ -2212,13 +2213,13 @@ SRST This option is deprecated and should no longer be used. The new ``sasl-authz`` and ``tls-authz`` options are a replacement. - ``lossy`` + ``lossy=on|off`` Enable lossy compression methods (gradient, JPEG, ...). If this option is set, VNC client may receive lossy framebuffer updates depending on its encoding settings. Enabling this option can save a lot of bandwidth at the expense of quality. - ``non-adaptive`` + ``non-adaptive=on|off`` Disable adaptive encodings. Adaptive encodings are enabled by default. An adaptive encoding will try to detect frequently updated screen regions, and send updates in these regions using @@ -2253,7 +2254,7 @@ SRST must be omitted, otherwise is must be present and specify a valid audiodev. - ``power-control`` + ``power-control=on|off`` Permit the remote client to issue shutdown, reboot or reset power control requests. ERST @@ -2405,8 +2406,8 @@ DEFHEADING(Network options:) DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, #ifdef CONFIG_SLIRP - "-netdev user,id=str[,ipv4[=on|off]][,net=addr[/mask]][,host=addr]\n" - " [,ipv6[=on|off]][,ipv6-net=addr[/int]][,ipv6-host=addr]\n" + "-netdev user,id=str[,ipv4=on|off][,net=addr[/mask]][,host=addr]\n" + " [,ipv6=on|off][,ipv6-net=addr[/int]][,ipv6-host=addr]\n" " [,restrict=on|off][,hostname=host][,dhcpstart=addr]\n" " [,dns=addr][,ipv6-dns=addr][,dnssearch=domain][,domainname=domain]\n" " [,tftp=dir][,tftp-server-name=name][,bootfile=f][,hostfwd=rule][,guestfwd=rule]" @@ -2453,8 +2454,8 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, #endif #ifdef __linux__ "-netdev l2tpv3,id=str,src=srcaddr,dst=dstaddr[,srcport=srcport][,dstport=dstport]\n" - " [,rxsession=rxsession],txsession=txsession[,ipv6=on/off][,udp=on/off]\n" - " [,cookie64=on/off][,counter][,pincounter][,txcookie=txcookie]\n" + " [,rxsession=rxsession],txsession=txsession[,ipv6=on|off][,udp=on|off]\n" + " [,cookie64=on|off][,counter][,pincounter][,txcookie=txcookie]\n" " [,rxcookie=rxcookie][,offset=offset]\n" " configure a network backend with ID 'str' connected to\n" " an Ethernet over L2TPv3 pseudowire.\n" @@ -2883,7 +2884,7 @@ SRST -device e1000,netdev=n1,mac=52:54:00:12:34:56 \\ -netdev socket,id=n1,mcast=239.192.168.1:1102,localaddr=1.2.3.4 -``-netdev l2tpv3,id=id,src=srcaddr,dst=dstaddr[,srcport=srcport][,dstport=dstport],txsession=txsession[,rxsession=rxsession][,ipv6][,udp][,cookie64][,counter][,pincounter][,txcookie=txcookie][,rxcookie=rxcookie][,offset=offset]`` +``-netdev l2tpv3,id=id,src=srcaddr,dst=dstaddr[,srcport=srcport][,dstport=dstport],txsession=txsession[,rxsession=rxsession][,ipv6=on|off][,udp=on|off][,cookie64][,counter][,pincounter][,txcookie=txcookie][,rxcookie=rxcookie][,offset=offset]`` Configure a L2TPv3 pseudowire host network backend. L2TPv3 (RFC3931) is a popular protocol to transport Ethernet (and other Layer 2) data frames between two systems. It is present in routers, firewalls and @@ -3032,13 +3033,13 @@ DEFHEADING(Character device options:) DEF("chardev", HAS_ARG, QEMU_OPTION_chardev, "-chardev help\n" "-chardev null,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" - "-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4][,ipv6][,nodelay][,reconnect=seconds]\n" - " [,server][,nowait][,telnet][,websocket][,reconnect=seconds][,mux=on|off]\n" + "-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4=on|off][,ipv6=on|off][,delay=on|off][,reconnect=seconds]\n" + " [,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off]\n" " [,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] (tcp)\n" - "-chardev socket,id=id,path=path[,server][,nowait][,telnet][,websocket][,reconnect=seconds]\n" + "-chardev socket,id=id,path=path[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds]\n" " [,mux=on|off][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off] (unix)\n" "-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]\n" - " [,localport=localport][,ipv4][,ipv6][,mux=on|off]\n" + " [,localport=localport][,ipv4=on|off][,ipv6=on|off][,mux=on|off]\n" " [,logfile=PATH][,logappend=on|off]\n" "-chardev msmouse,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" "-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n" @@ -3148,21 +3149,21 @@ The available backends are: A void device. This device will not emit any data, and will drop any data it receives. The null backend does not take any options. -``-chardev socket,id=id[,TCP options or unix options][,server][,nowait][,telnet][,websocket][,reconnect=seconds][,tls-creds=id][,tls-authz=id]`` +``-chardev socket,id=id[,TCP options or unix options][,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,tls-creds=id][,tls-authz=id]`` Create a two-way stream socket, which can be either a TCP or a unix socket. A unix socket will be created if ``path`` is specified. Behaviour is undefined if TCP options are specified for a unix socket. - ``server`` specifies that the socket shall be a listening socket. + ``server=on|off`` specifies that the socket shall be a listening socket. - ``nowait`` specifies that QEMU should not block waiting for a client + ``wait=on|off`` specifies that QEMU should not block waiting for a client to connect to a listening socket. - ``telnet`` specifies that traffic on the socket should interpret + ``telnet=on|off`` specifies that traffic on the socket should interpret telnet escape sequences. - ``websocket`` specifies that the socket uses WebSocket protocol for + ``websocket=on|off`` specifies that the socket uses WebSocket protocol for communication. ``reconnect`` sets the timeout for reconnecting on non-server @@ -3183,7 +3184,7 @@ The available backends are: TCP and unix socket options are given below: - ``TCP options: port=port[,host=host][,to=to][,ipv4][,ipv6][,nodelay]`` + ``TCP options: port=port[,host=host][,to=to][,ipv4=on|off][,ipv6=on|off][,delay=on|off]`` ``host`` for a listening socket specifies the local address to be bound. For a connecting socket species the remote host to connect to. ``host`` is optional for listening sockets. If not @@ -3199,21 +3200,21 @@ The available backends are: bind to subsequent ports up to and including ``to`` until it succeeds. ``to`` must be specified as a port number. - ``ipv4`` and ``ipv6`` specify that either IPv4 or IPv6 must be - used. If neither is specified the socket may use either - protocol. + ``ipv4=on|off`` and ``ipv6=on|off`` specify that either IPv4 + or IPv6 must be used. If neither is specified the socket may + use either protocol. - ``nodelay`` disables the Nagle algorithm. + ``delay=on|off`` disables the Nagle algorithm. ``unix options: path=path[,abstract=on|off][,tight=on|off]`` ``path`` specifies the local path of the unix socket. ``path`` is required. - ``abstract`` specifies the use of the abstract socket namespace, + ``abstract=on|off`` specifies the use of the abstract socket namespace, rather than the filesystem. Optional, defaults to false. - ``tight`` sets the socket length of abstract sockets to their minimum, + ``tight=on|off`` sets the socket length of abstract sockets to their minimum, rather than the full sun_path length. Optional, defaults to true. -``-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr][,localport=localport][,ipv4][,ipv6]`` +``-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr][,localport=localport][,ipv4=on|off][,ipv6=on|off]`` Sends all traffic from the guest to a remote host over UDP. ``host`` specifies the remote host to connect to. If not specified @@ -3228,7 +3229,7 @@ The available backends are: ``localport`` specifies the local port to bind to. If not specified any available local port will be used. - ``ipv4`` and ``ipv6`` specify that either IPv4 or IPv6 must be used. + ``ipv4=on|off`` and ``ipv6=on|off`` specify that either IPv4 or IPv6 must be used. If neither is specified the device may use either protocol. ``-chardev msmouse,id=id`` @@ -3592,30 +3593,30 @@ SRST ``telnet options:`` localhost 5555 - ``tcp:[host]:port[,server][,nowait][,nodelay][,reconnect=seconds]`` + ``tcp:[host]:port[,server=on|off][,wait=on|off][,delay=on|off][,reconnect=seconds]`` The TCP Net Console has two modes of operation. It can send the serial I/O to a location or wait for a connection from a location. By default the TCP Net Console is sent to host at the - port. If you use the server option QEMU will wait for a client + port. If you use the ``server=on`` option QEMU will wait for a client socket application to connect to the port before continuing, - unless the ``nowait`` option was specified. The ``nodelay`` - option disables the Nagle buffering algorithm. The ``reconnect`` - option only applies if noserver is set, if the connection goes + unless the ``wait=on|off`` option was specified. The ``delay=on|off`` + option disables the Nagle buffering algorithm. The ``reconnect=on`` + option only applies if ``server=no`` is set, if the connection goes down it will attempt to reconnect at the given interval. If host is omitted, 0.0.0.0 is assumed. Only one TCP connection at a - time is accepted. You can use ``telnet`` to connect to the + time is accepted. You can use ``telnet=on`` to connect to the corresponding character device. ``Example to send tcp console to 192.168.0.2 port 4444`` -serial tcp:192.168.0.2:4444 ``Example to listen and wait on port 4444 for connection`` - -serial tcp::4444,server + -serial tcp::4444,server=on ``Example to not wait and listen on ip 192.168.0.100 port 4444`` - -serial tcp:192.168.0.100:4444,server,nowait + -serial tcp:192.168.0.100:4444,server=on,wait=off - ``telnet:host:port[,server][,nowait][,nodelay]`` + ``telnet:host:port[,server=on|off][,wait=on|off][,delay=on|off]`` The telnet protocol is used instead of raw tcp sockets. The options work the same as if you had specified ``-serial tcp``. The difference is that the port acts like a telnet server or @@ -3625,11 +3626,11 @@ SRST you do it with Control-] and then type "send break" followed by pressing the enter key. - ``websocket:host:port,server[,nowait][,nodelay]`` + ``websocket:host:port,server=on[,wait=on|off][,delay=on|off]`` The WebSocket protocol is used instead of raw tcp socket. The port acts as a WebSocket server. Client mode is not supported. - ``unix:path[,server][,nowait][,reconnect=seconds]`` + ``unix:path[,server=on|off][,wait=on|off][,reconnect=seconds]`` A unix domain socket is used instead of a tcp socket. The option works the same as if you had specified ``-serial tcp`` except the unix domain socket path is used for connections. @@ -3642,7 +3643,7 @@ SRST multiplex the monitor onto a telnet server listening on port 4444 would be: - ``-serial mon:telnet::4444,server,nowait`` + ``-serial mon:telnet::4444,server=on,wait=off`` When the monitor is multiplexed to stdio in this way, Ctrl+C will not terminate QEMU any more but will be passed to the guest @@ -4134,8 +4135,8 @@ SRST ERST DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \ - "-incoming tcp:[host]:port[,to=maxport][,ipv4][,ipv6]\n" \ - "-incoming rdma:host:port[,ipv4][,ipv6]\n" \ + "-incoming tcp:[host]:port[,to=maxport][,ipv4=on|off][,ipv6=on|off]\n" \ + "-incoming rdma:host:port[,ipv4=on|off][,ipv6=on|off]\n" \ "-incoming unix:socketpath\n" \ " prepare for incoming migration, listen on\n" \ " specified protocol and socket address\n" \ @@ -4147,9 +4148,9 @@ DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \ " wait for the URI to be specified via migrate_incoming\n", QEMU_ARCH_ALL) SRST -``-incoming tcp:[host]:port[,to=maxport][,ipv4][,ipv6]`` +``-incoming tcp:[host]:port[,to=maxport][,ipv4=on|off][,ipv6=on|off]`` \ -``-incoming rdma:host:port[,ipv4][,ipv6]`` +``-incoming rdma:host:port[,ipv4=on|off][,ipv6=on|off]`` Prepare for incoming migration, listen on a given tcp port. ``-incoming unix:socketpath`` @@ -4334,13 +4335,8 @@ SRST ERST DEF("writeconfig", HAS_ARG, QEMU_OPTION_writeconfig, "-writeconfig <file>\n" - " read/write config file\n", QEMU_ARCH_ALL) + " read/write config file (deprecated)\n", QEMU_ARCH_ALL) SRST -``-writeconfig file`` - Write device configuration to file. The file can be either filename - to save command line and device configuration into file or dash - ``-``) character to print the output to stdout. This can be later - used as input file for ``-readconfig`` option. ERST DEF("no-user-config", 0, QEMU_OPTION_nouserconfig, @@ -4815,11 +4811,11 @@ SRST primary: -netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown -device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66 - -chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait - -chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait - -chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait + -chardev socket,id=mirror0,host=3.3.3.3,port=9003,server=on,wait=off + -chardev socket,id=compare1,host=3.3.3.3,port=9004,server=on,wait=off + -chardev socket,id=compare0,host=3.3.3.3,port=9001,server=on,wait=off -chardev socket,id=compare0-0,host=3.3.3.3,port=9001 - -chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait + -chardev socket,id=compare_out,host=3.3.3.3,port=9005,server=on,wait=off -chardev socket,id=compare_out0,host=3.3.3.3,port=9005 -object iothread,id=iothread1 -object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0 @@ -4841,13 +4837,13 @@ SRST primary: -netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown -device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66 - -chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait - -chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait - -chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait + -chardev socket,id=mirror0,host=3.3.3.3,port=9003,server=on,wait=off + -chardev socket,id=compare1,host=3.3.3.3,port=9004,server=on,wait=off + -chardev socket,id=compare0,host=3.3.3.3,port=9001,server=on,wait=off -chardev socket,id=compare0-0,host=3.3.3.3,port=9001 - -chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait + -chardev socket,id=compare_out,host=3.3.3.3,port=9005,server=on,wait=off -chardev socket,id=compare_out0,host=3.3.3.3,port=9005 - -chardev socket,id=notify_way,host=3.3.3.3,port=9009,server,nowait + -chardev socket,id=notify_way,host=3.3.3.3,port=9009,server=on,wait=off -object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0 -object filter-redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out -object filter-redirector,netdev=hn0,id=redire1,queue=rx,outdev=compare0 diff --git a/qom/object.c b/qom/object.c index 491823d..6a01d56 100644 --- a/qom/object.c +++ b/qom/object.c @@ -695,7 +695,7 @@ static void object_finalize(void *data) /* Find the minimum alignment guaranteed by the system malloc. */ #if __STDC_VERSION__ >= 201112L -typddef max_align_t qemu_max_align_t; +typedef max_align_t qemu_max_align_t; #else typedef union { long l; diff --git a/scripts/entitlement.sh b/scripts/entitlement.sh index c540fa6..f7aaaf2 100755 --- a/scripts/entitlement.sh +++ b/scripts/entitlement.sh @@ -2,12 +2,24 @@ # # Helper script for the build process to apply entitlements +in_place=: +if [ "$1" = --install ]; then + shift + in_place=false +fi + SRC="$1" DST="$2" ENTITLEMENT="$3" -trap 'rm "$DST.tmp"' exit -cp -af "$SRC" "$DST.tmp" -codesign --entitlements "$ENTITLEMENT" --force -s - "$DST.tmp" -mv "$DST.tmp" "$DST" +if $in_place; then + trap 'rm "$DST.tmp"' exit + cp -af "$SRC" "$DST.tmp" + SRC="$DST.tmp" +else + cd "$MESON_INSTALL_DESTDIR_PREFIX" +fi + +codesign --entitlements "$ENTITLEMENT" --force -s - "$SRC" +mv -f "$SRC" "$DST" trap '' exit diff --git a/scripts/qmp/qemu-ga-client b/scripts/qmp/qemu-ga-client index ce12298..348d858 100755 --- a/scripts/qmp/qemu-ga-client +++ b/scripts/qmp/qemu-ga-client @@ -11,7 +11,7 @@ # # Start QEMU with: # -# # qemu [...] -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \ +# # qemu [...] -chardev socket,path=/tmp/qga.sock,server=on,wait=off,id=qga0 \ # -device virtio-serial -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 # # Run the script: diff --git a/scsi/utils.c b/scsi/utils.c index 793c3a6..6b56e01 100644 --- a/scsi/utils.c +++ b/scsi/utils.c @@ -565,21 +565,52 @@ const char *scsi_command_name(uint8_t cmd) return names[cmd]; } +int scsi_sense_from_errno(int errno_value, SCSISense *sense) +{ + switch (errno_value) { + case 0: + return GOOD; + case EDOM: + return TASK_SET_FULL; +#ifdef CONFIG_LINUX + /* These errno mapping are specific to Linux. For more information: + * - scsi_decide_disposition in drivers/scsi/scsi_error.c + * - scsi_result_to_blk_status in drivers/scsi/scsi_lib.c + * - blk_errors[] in block/blk-core.c + */ + case EBADE: + return RESERVATION_CONFLICT; + case ENODATA: + *sense = SENSE_CODE(READ_ERROR); + return CHECK_CONDITION; + case EREMOTEIO: + *sense = SENSE_CODE(LUN_COMM_FAILURE); + return CHECK_CONDITION; +#endif + case ENOMEDIUM: + *sense = SENSE_CODE(NO_MEDIUM); + return CHECK_CONDITION; + case ENOMEM: + *sense = SENSE_CODE(TARGET_FAILURE); + return CHECK_CONDITION; + case EINVAL: + *sense = SENSE_CODE(INVALID_FIELD); + return CHECK_CONDITION; + case ENOSPC: + *sense = SENSE_CODE(SPACE_ALLOC_FAILED); + return CHECK_CONDITION; + default: + *sense = SENSE_CODE(IO_ERROR); + return CHECK_CONDITION; + } +} + #ifdef CONFIG_LINUX int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr, SCSISense *sense) { if (errno_value != 0) { - switch (errno_value) { - case EDOM: - return TASK_SET_FULL; - case ENOMEM: - *sense = SENSE_CODE(TARGET_FAILURE); - return CHECK_CONDITION; - default: - *sense = SENSE_CODE(IO_ERROR); - return CHECK_CONDITION; - } + return scsi_sense_from_errno(errno_value, sense); } else { if (io_hdr->host_status == SG_ERR_DID_NO_CONNECT || io_hdr->host_status == SG_ERR_DID_BUS_BUSY || diff --git a/softmmu/vl.c b/softmmu/vl.c index b219ce1..10bd8a1 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -3356,6 +3356,7 @@ void qemu_init(int argc, char **argv, char **envp) case QEMU_OPTION_writeconfig: { FILE *fp; + warn_report("-writeconfig is deprecated and will go away without a replacement"); if (strcmp(optarg, "-") == 0) { fp = stdout; } else { diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 6a53446..5000843 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -963,7 +963,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "avx512bitalg", NULL, "avx512-vpopcntdq", NULL, "la57", NULL, NULL, NULL, NULL, NULL, "rdpid", NULL, - NULL, "cldemote", NULL, "movdiri", + "bus-lock-detect", "cldemote", NULL, "movdiri", "movdir64b", NULL, NULL, "pks", }, .cpuid = { @@ -6557,7 +6557,7 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) } else if (cpu->env.cpuid_min_level < 0x14) { mark_unavailable_features(cpu, FEAT_7_0_EBX, CPUID_7_0_EBX_INTEL_PT, - "Intel PT need CPUID leaf 0x14, please set by \"-cpu ...,+intel-pt,min-level=0x14\""); + "Intel PT need CPUID leaf 0x14, please set by \"-cpu ...,intel-pt=on,min-level=0x14\""); } } diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 8be39cf..b4b136c 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -769,6 +769,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; #define CPUID_7_0_ECX_LA57 (1U << 16) /* Read Processor ID */ #define CPUID_7_0_ECX_RDPID (1U << 22) +/* Bus Lock Debug Exception */ +#define CPUID_7_0_ECX_BUS_LOCK_DETECT (1U << 24) /* Cache Line Demote Instruction */ #define CPUID_7_0_ECX_CLDEMOTE (1U << 25) /* Move Doubleword as Direct Store Instruction */ diff --git a/target/i386/tcg/misc_helper.c b/target/i386/tcg/misc_helper.c index f02e4fd..90b87fd 100644 --- a/target/i386/tcg/misc_helper.c +++ b/target/i386/tcg/misc_helper.c @@ -222,7 +222,8 @@ void helper_rdtscp(CPUX86State *env) void helper_rdpmc(CPUX86State *env) { - if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { + if (((env->cr[4] & CR4_PCE_MASK) == 0 ) && + ((env->hflags & HF_CPL_MASK) != 0)) { raise_exception_ra(env, EXCP0D_GPF, GETPC()); } cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC()); diff --git a/tests/guest-debug/run-test.py b/tests/guest-debug/run-test.py index 8b91ff9..2e58795 100755 --- a/tests/guest-debug/run-test.py +++ b/tests/guest-debug/run-test.py @@ -64,10 +64,10 @@ if __name__ == '__main__': # Launch QEMU with binary if "system" in args.qemu: - cmd = "%s %s %s -gdb unix:path=%s,server" % (args.qemu, - args.qargs, - args.binary, - socket_name) + cmd = "%s %s %s -gdb unix:path=%s,server=on" % (args.qemu, + args.qargs, + args.binary, + socket_name) else: cmd = "%s %s -g %s %s" % (args.qemu, args.qargs, socket_name, args.binary) diff --git a/tests/qtest/test-x86-cpuid-compat.c b/tests/qtest/test-x86-cpuid-compat.c index 7ca1883..6470f0a 100644 --- a/tests/qtest/test-x86-cpuid-compat.c +++ b/tests/qtest/test-x86-cpuid-compat.c @@ -235,82 +235,82 @@ int main(int argc, char **argv) /* If level is not large enough, it should increase automatically: */ /* CPUID[6].EAX: */ add_cpuid_test("x86/cpuid/auto-level/phenom/arat", - "-cpu 486,+arat", "level", 6); + "-cpu 486,arat=on", "level", 6); /* CPUID[EAX=7,ECX=0].EBX: */ add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase", - "-cpu phenom,+fsgsbase", "level", 7); + "-cpu phenom,fsgsbase=on", "level", 7); /* CPUID[EAX=7,ECX=0].ECX: */ add_cpuid_test("x86/cpuid/auto-level/phenom/avx512vbmi", - "-cpu phenom,+avx512vbmi", "level", 7); + "-cpu phenom,avx512vbmi=on", "level", 7); /* CPUID[EAX=0xd,ECX=1].EAX: */ add_cpuid_test("x86/cpuid/auto-level/phenom/xsaveopt", - "-cpu phenom,+xsaveopt", "level", 0xd); + "-cpu phenom,xsaveopt=on", "level", 0xd); /* CPUID[8000_0001].EDX: */ add_cpuid_test("x86/cpuid/auto-xlevel/486/3dnow", - "-cpu 486,+3dnow", "xlevel", 0x80000001); + "-cpu 486,3dnow=on", "xlevel", 0x80000001); /* CPUID[8000_0001].ECX: */ add_cpuid_test("x86/cpuid/auto-xlevel/486/sse4a", - "-cpu 486,+sse4a", "xlevel", 0x80000001); + "-cpu 486,sse4a=on", "xlevel", 0x80000001); /* CPUID[8000_0007].EDX: */ add_cpuid_test("x86/cpuid/auto-xlevel/486/invtsc", - "-cpu 486,+invtsc", "xlevel", 0x80000007); + "-cpu 486,invtsc=on", "xlevel", 0x80000007); /* CPUID[8000_000A].EDX: */ add_cpuid_test("x86/cpuid/auto-xlevel/486/npt", - "-cpu 486,+svm,+npt", "xlevel", 0x8000000A); + "-cpu 486,svm=on,npt=on", "xlevel", 0x8000000A); /* CPUID[C000_0001].EDX: */ add_cpuid_test("x86/cpuid/auto-xlevel2/phenom/xstore", - "-cpu phenom,+xstore", "xlevel2", 0xC0000001); + "-cpu phenom,xstore=on", "xlevel2", 0xC0000001); /* SVM needs CPUID[0x8000000A] */ add_cpuid_test("x86/cpuid/auto-xlevel/athlon/svm", - "-cpu athlon,+svm", "xlevel", 0x8000000A); + "-cpu athlon,svm=on", "xlevel", 0x8000000A); /* If level is already large enough, it shouldn't change: */ add_cpuid_test("x86/cpuid/auto-level/SandyBridge/multiple", - "-cpu SandyBridge,+arat,+fsgsbase,+avx512vbmi", + "-cpu SandyBridge,arat=on,fsgsbase=on,avx512vbmi=on", "level", 0xd); /* If level is explicitly set, it shouldn't change: */ add_cpuid_test("x86/cpuid/auto-level/486/fixed/0xF", - "-cpu 486,level=0xF,+arat,+fsgsbase,+avx512vbmi,+xsaveopt", + "-cpu 486,level=0xF,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", "level", 0xF); add_cpuid_test("x86/cpuid/auto-level/486/fixed/2", - "-cpu 486,level=2,+arat,+fsgsbase,+avx512vbmi,+xsaveopt", + "-cpu 486,level=2,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", "level", 2); add_cpuid_test("x86/cpuid/auto-level/486/fixed/0", - "-cpu 486,level=0,+arat,+fsgsbase,+avx512vbmi,+xsaveopt", + "-cpu 486,level=0,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", "level", 0); /* if xlevel is already large enough, it shouldn't change: */ add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow", - "-cpu phenom,+3dnow,+sse4a,+invtsc,+npt,+svm", + "-cpu phenom,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", "xlevel", 0x8000001A); /* If xlevel is explicitly set, it shouldn't change: */ add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/80000002", - "-cpu 486,xlevel=0x80000002,+3dnow,+sse4a,+invtsc,+npt,+svm", + "-cpu 486,xlevel=0x80000002,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", "xlevel", 0x80000002); add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/8000001A", - "-cpu 486,xlevel=0x8000001A,+3dnow,+sse4a,+invtsc,+npt,+svm", + "-cpu 486,xlevel=0x8000001A,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", "xlevel", 0x8000001A); add_cpuid_test("x86/cpuid/auto-xlevel/phenom/fixed/0", - "-cpu 486,xlevel=0,+3dnow,+sse4a,+invtsc,+npt,+svm", + "-cpu 486,xlevel=0,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", "xlevel", 0); /* if xlevel2 is already large enough, it shouldn't change: */ add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed", - "-cpu 486,xlevel2=0xC0000002,+xstore", + "-cpu 486,xlevel2=0xC0000002,xstore=on", "xlevel2", 0xC0000002); /* Check compatibility of old machine-types that didn't * auto-increase level/xlevel/xlevel2: */ add_cpuid_test("x86/cpuid/auto-level/pc-2.7", - "-machine pc-i440fx-2.7 -cpu 486,+arat,+avx512vbmi,+xsaveopt", + "-machine pc-i440fx-2.7 -cpu 486,arat=on,avx512vbmi=on,xsaveopt=on", "level", 1); add_cpuid_test("x86/cpuid/auto-xlevel/pc-2.7", - "-machine pc-i440fx-2.7 -cpu 486,+3dnow,+sse4a,+invtsc,+npt,+svm", + "-machine pc-i440fx-2.7 -cpu 486,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", "xlevel", 0); add_cpuid_test("x86/cpuid/auto-xlevel2/pc-2.7", - "-machine pc-i440fx-2.7 -cpu 486,+xstore", + "-machine pc-i440fx-2.7 -cpu 486,xstore=on", "xlevel2", 0); /* * QEMU 1.4.0 had auto-level enabled for CPUID[7], already, @@ -321,19 +321,19 @@ int main(int argc, char **argv) "-machine pc-i440fx-1.4 -cpu Nehalem", "level", 2); add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-1.5/on", - "-machine pc-i440fx-1.4 -cpu Nehalem,+smap", + "-machine pc-i440fx-1.4 -cpu Nehalem,smap=on", "level", 7); add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/off", "-machine pc-i440fx-2.3 -cpu Penryn", "level", 4); add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/on", - "-machine pc-i440fx-2.3 -cpu Penryn,+erms", + "-machine pc-i440fx-2.3 -cpu Penryn,erms=on", "level", 7); add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/off", "-machine pc-i440fx-2.9 -cpu Conroe", "level", 10); add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/on", - "-machine pc-i440fx-2.9 -cpu Conroe,+erms", + "-machine pc-i440fx-2.9 -cpu Conroe,erms=on", "level", 10); /* @@ -348,7 +348,7 @@ int main(int argc, char **argv) "-machine pc-i440fx-2.4 -cpu SandyBridge,", "xlevel", 0x80000008); add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-on", - "-machine pc-i440fx-2.4 -cpu SandyBridge,+svm,+npt", + "-machine pc-i440fx-2.4 -cpu SandyBridge,svm=on,npt=on", "xlevel", 0x80000008); /* Test feature parsing */ diff --git a/tests/test-char.c b/tests/test-char.c index 469d259..755d54c 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -780,7 +780,7 @@ static void char_socket_server_test(gconstpointer opaque) g_setenv("QTEST_SILENT_ERRORS", "1", 1); /* - * We rely on config->addr containing "nowait", otherwise + * We rely on config->addr containing "wait=off", otherwise * qemu_chr_new() will block until a client connects. We * can't spawn our client thread though, because until * qemu_chr_new() returns we don't know what TCP port was @@ -1114,7 +1114,7 @@ static void char_socket_server_two_clients_test(gconstpointer opaque) g_setenv("QTEST_SILENT_ERRORS", "1", 1); /* - * We rely on addr containing "nowait", otherwise + * We rely on addr containing "wait=off", otherwise * qemu_chr_new() will block until a client connects. We * can't spawn our client thread though, because until * qemu_chr_new() returns we don't know what TCP port was |