aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.mailmap16
-rw-r--r--.travis.yml4
-rw-r--r--MAINTAINERS48
-rw-r--r--accel/accel-system.c (renamed from accel/accel-softmmu.c)6
-rw-r--r--accel/accel-system.h (renamed from accel/accel-softmmu.h)6
-rw-r--r--accel/accel-target.c2
-rw-r--r--accel/meson.build2
-rw-r--r--accel/stubs/meson.build10
-rw-r--r--accel/tcg/icount-common.c2
-rw-r--r--accel/tcg/user-exec.c2
-rw-r--r--audio/audio.c85
-rw-r--r--audio/audio.h3
-rw-r--r--audio/ossaudio.c1
-rw-r--r--block/nbd.c67
-rw-r--r--block/trace-events1
-rwxr-xr-xconfigure10
-rw-r--r--cpu-target.c2
-rw-r--r--docs/about/deprecated.rst6
-rw-r--r--docs/about/removed-features.rst22
-rw-r--r--docs/devel/build-system.rst4
-rw-r--r--docs/devel/qtest.rst2
-rw-r--r--docs/devel/testing.rst2
-rw-r--r--docs/interop/nbd.txt1
-rw-r--r--dump/dump.c8
-rw-r--r--gdbstub/internals.h4
-rw-r--r--gdbstub/meson.build10
-rw-r--r--gdbstub/system.c (renamed from gdbstub/softmmu.c)2
-rw-r--r--gdbstub/trace-events2
-rw-r--r--hw/audio/Kconfig3
-rw-r--r--hw/audio/asc.c727
-rw-r--r--hw/audio/meson.build1
-rw-r--r--hw/audio/soundhw.c6
-rw-r--r--hw/audio/trace-events10
-rw-r--r--hw/block/swim.c261
-rw-r--r--hw/block/trace-events8
-rw-r--r--hw/core/cpu-common.c4
-rw-r--r--hw/cxl/cxl-device-utils.c8
-rw-r--r--hw/i386/acpi-microvm.c4
-rw-r--r--hw/i386/pc.c1
-rw-r--r--hw/i386/x86.c2
-rw-r--r--hw/ide/ahci.c4
-rw-r--r--hw/loongarch/virt.c2
-rw-r--r--hw/m68k/Kconfig3
-rw-r--r--hw/m68k/q800-glue.c18
-rw-r--r--hw/m68k/q800.c138
-rw-r--r--hw/misc/Kconfig6
-rw-r--r--hw/misc/djmemc.c135
-rw-r--r--hw/misc/iosb.c133
-rw-r--r--hw/misc/mac_via.c234
-rw-r--r--hw/misc/meson.build2
-rw-r--r--hw/misc/trace-events10
-rw-r--r--hw/net/vhost_net.c8
-rw-r--r--hw/usb/desc.c2
-rw-r--r--hw/usb/dev-hub.c8
-rw-r--r--hw/usb/dev-storage.c6
-rw-r--r--hw/usb/hcd-xhci.c10
-rw-r--r--hw/usb/host-libusb.c2
-rw-r--r--hw/vfio/display.c2
-rw-r--r--hw/vfio/pci.c127
-rw-r--r--hw/vfio/pci.h1
-rw-r--r--hw/vfio/trace-events2
-rw-r--r--hw/virtio/vhost.c8
-rw-r--r--hw/virtio/virtio-pci.c20
-rw-r--r--include/block/nbd.h5
-rw-r--r--include/hw/audio/asc.h86
-rw-r--r--include/hw/audio/soundhw.h2
-rw-r--r--include/hw/block/swim.h21
-rw-r--r--include/hw/m68k/q800-glue.h4
-rw-r--r--include/hw/m68k/q800.h11
-rw-r--r--include/hw/misc/djmemc.h30
-rw-r--r--include/hw/misc/iosb.h25
-rw-r--r--include/hw/misc/mac_via.h3
-rw-r--r--include/net/net.h6
-rw-r--r--include/qemu/atomic128.h4
-rw-r--r--include/qemu/guest-random.h8
-rw-r--r--include/qemu/plugin.h4
-rw-r--r--include/qom/object_interfaces.h16
-rw-r--r--include/semihosting/semihost.h2
-rw-r--r--include/semihosting/uaccess.h (renamed from include/semihosting/softmmu-uaccess.h)24
-rw-r--r--include/sysemu/cpu-timers-internal.h (renamed from softmmu/timers-state.h)0
-rw-r--r--include/sysemu/hvf.h3
-rw-r--r--include/sysemu/os-posix.h4
-rw-r--r--include/sysemu/runstate-action.h2
-rw-r--r--include/sysemu/tpm.h2
-rw-r--r--include/tcg/tcg-op-common.h2
-rw-r--r--linux-user/flatload.c8
-rw-r--r--linux-user/mmap.c6
-rw-r--r--linux-user/syscall.c36
-rw-r--r--meson.build22
-rw-r--r--migration/dirtyrate.c122
-rw-r--r--migration/dirtyrate.h12
-rw-r--r--nbd/client-connection.c2
-rw-r--r--nbd/client.c124
-rw-r--r--nbd/nbd-internal.h5
-rw-r--r--nbd/server.c424
-rw-r--r--nbd/trace-events5
-rw-r--r--net/net.c14
-rw-r--r--os-posix.c12
-rw-r--r--plugins/loader.c4
-rw-r--r--qapi/migration.json58
-rw-r--r--qemu-img.c22
-rw-r--r--qemu-io.c4
-rw-r--r--qemu-nbd.c4
-rw-r--r--qemu-options.hx29
-rw-r--r--qom/object_interfaces.c16
-rwxr-xr-xscripts/checkpatch.pl2
-rw-r--r--scripts/coverity-scan/COMPONENTS.md2
-rwxr-xr-xscripts/get_maintainer.pl2
-rwxr-xr-xscripts/oss-fuzz/build.sh6
-rw-r--r--semihosting/arm-compat-semi.c9
-rw-r--r--semihosting/config.c10
-rw-r--r--semihosting/guestfd.c2
-rw-r--r--semihosting/syscalls.c2
-rw-r--r--semihosting/uaccess.c14
-rw-r--r--softmmu/trace.h1
-rw-r--r--stubs/semihost.c6
-rw-r--r--system/arch_init.c (renamed from softmmu/arch_init.c)0
-rw-r--r--system/async-teardown.c (renamed from softmmu/async-teardown.c)0
-rw-r--r--system/balloon.c (renamed from softmmu/balloon.c)0
-rw-r--r--system/bootdevice.c (renamed from softmmu/bootdevice.c)0
-rw-r--r--system/cpu-throttle.c (renamed from softmmu/cpu-throttle.c)0
-rw-r--r--system/cpu-timers.c (renamed from softmmu/cpu-timers.c)2
-rw-r--r--system/cpus.c (renamed from softmmu/cpus.c)0
-rw-r--r--system/datadir.c (renamed from softmmu/datadir.c)0
-rw-r--r--system/device_tree.c (renamed from softmmu/device_tree.c)0
-rw-r--r--system/dirtylimit.c (renamed from softmmu/dirtylimit.c)0
-rw-r--r--system/dma-helpers.c (renamed from softmmu/dma-helpers.c)0
-rw-r--r--system/globals.c (renamed from softmmu/globals.c)0
-rw-r--r--system/ioport.c (renamed from softmmu/ioport.c)0
-rw-r--r--system/main.c (renamed from softmmu/main.c)0
-rw-r--r--system/memory.c (renamed from softmmu/memory.c)2
-rw-r--r--system/memory_mapping.c (renamed from softmmu/memory_mapping.c)0
-rw-r--r--system/meson.build (renamed from softmmu/meson.build)0
-rw-r--r--system/physmem.c (renamed from softmmu/physmem.c)6
-rw-r--r--system/qdev-monitor.c (renamed from softmmu/qdev-monitor.c)0
-rw-r--r--system/qemu-seccomp.c (renamed from softmmu/qemu-seccomp.c)0
-rw-r--r--system/qtest.c (renamed from softmmu/qtest.c)0
-rw-r--r--system/rtc.c (renamed from softmmu/rtc.c)0
-rw-r--r--system/runstate-action.c (renamed from softmmu/runstate-action.c)0
-rw-r--r--system/runstate-hmp-cmds.c (renamed from softmmu/runstate-hmp-cmds.c)0
-rw-r--r--system/runstate.c (renamed from softmmu/runstate.c)0
-rw-r--r--system/tpm-hmp-cmds.c (renamed from softmmu/tpm-hmp-cmds.c)0
-rw-r--r--system/tpm.c (renamed from softmmu/tpm.c)6
-rw-r--r--system/trace-events (renamed from softmmu/trace-events)2
-rw-r--r--system/trace.h1
-rw-r--r--system/vl.c (renamed from softmmu/vl.c)60
-rw-r--r--system/watchpoint.c (renamed from softmmu/watchpoint.c)0
-rw-r--r--target/alpha/meson.build2
-rw-r--r--target/arm/meson.build2
-rw-r--r--target/avr/meson.build2
-rw-r--r--target/cris/meson.build2
-rw-r--r--target/hppa/meson.build2
-rw-r--r--target/i386/cpu.c3
-rw-r--r--target/i386/hvf/hvf-cpu.c1
-rw-r--r--target/i386/hvf/hvf-i386.h6
-rw-r--r--target/i386/hvf/x86_cpuid.c1
-rw-r--r--target/i386/kvm/meson.build10
-rw-r--r--target/i386/meson.build2
-rw-r--r--target/i386/tcg/misc_helper.c2
-rw-r--r--target/i386/tcg/translate.c6
-rw-r--r--target/loongarch/meson.build2
-rw-r--r--target/m68k/m68k-semi.c2
-rw-r--r--target/m68k/meson.build2
-rw-r--r--target/microblaze/meson.build2
-rw-r--r--target/mips/meson.build2
-rw-r--r--target/mips/tcg/sysemu/mips-semi.c2
-rw-r--r--target/nios2/meson.build2
-rw-r--r--target/nios2/nios2-semi.c2
-rw-r--r--target/openrisc/meson.build2
-rw-r--r--target/ppc/int_helper.c12
-rw-r--r--target/ppc/kvm.c4
-rw-r--r--target/ppc/meson.build2
-rw-r--r--target/riscv/meson.build2
-rw-r--r--target/riscv/vector_helper.c2
-rw-r--r--target/rx/meson.build2
-rw-r--r--target/s390x/meson.build2
-rw-r--r--target/sh4/meson.build2
-rw-r--r--target/sparc/meson.build2
-rw-r--r--target/tricore/meson.build2
-rw-r--r--target/xtensa/meson.build2
-rw-r--r--tcg/aarch64/tcg-target.c.inc4
-rw-r--r--tcg/arm/tcg-target.c.inc2
-rw-r--r--tcg/i386/tcg-target.c.inc2
-rw-r--r--tcg/loongarch64/tcg-target.c.inc4
-rw-r--r--tcg/meson.build6
-rw-r--r--tcg/mips/tcg-target.c.inc4
-rw-r--r--tcg/ppc/tcg-target.c.inc4
-rw-r--r--tcg/region.c4
-rw-r--r--tcg/riscv/tcg-target.c.inc4
-rw-r--r--tcg/s390x/tcg-target.c.inc4
-rw-r--r--tcg/sparc64/tcg-target.c.inc4
-rw-r--r--tcg/tcg.c11
-rw-r--r--tests/qemu-iotests/223.out18
-rw-r--r--tests/qemu-iotests/233.out4
-rw-r--r--tests/qemu-iotests/241.out3
-rw-r--r--tests/qemu-iotests/307.out15
-rw-r--r--tests/qemu-iotests/tests/nbd-qemu-allocation.out3
-rw-r--r--tests/qtest/fuzz/fuzz.c2
-rw-r--r--tests/qtest/fuzz/fuzz.h4
-rw-r--r--tests/qtest/libqtest.c4
-rw-r--r--tests/tcg/Makefile.target2
-rw-r--r--tests/tcg/multiarch/gdbstub/interrupt.py2
-rw-r--r--tests/tcg/multiarch/gdbstub/memory.py2
-rw-r--r--tests/tcg/multiarch/system/memory.c4
-rw-r--r--tests/tcg/s390x/pgm-specification-softmmu.S2
-rw-r--r--tests/tcg/s390x/pgm-specification.mak2
-rw-r--r--tests/tcg/s390x/softmmu.ld2
-rw-r--r--tests/tcg/xtensa/Makefile.softmmu-target2
-rw-r--r--tests/tcg/xtensaeb/Makefile.softmmu-target2
-rw-r--r--tests/unit/meson.build2
-rw-r--r--trace/control.c4
-rw-r--r--trace/control.h4
-rw-r--r--ui/cocoa.m4
-rw-r--r--ui/vnc.c2
-rw-r--r--util/cutils.c10
-rw-r--r--util/guest-random.c6
-rw-r--r--util/log.c2
217 files changed, 3017 insertions, 810 deletions
diff --git a/.mailmap b/.mailmap
index 64ef9f4..d214959 100644
--- a/.mailmap
+++ b/.mailmap
@@ -40,12 +40,26 @@ Nick Hudson <hnick@vmware.com> hnick@vmware.com <hnick@vmware.com>
# for the cvs2svn initialization commit e63c3dc74bf.
# Next, translate a few commits where mailman rewrote the From: line due
-# to strict SPF, although we prefer to avoid adding more entries like that.
+# to strict SPF and DMARC. Usually, our build process should be flagging
+# commits like these before maintainer merges; if you find the need to add
+# a line here, please also report a bug against the part of the build
+# process that let the mis-attribution slip through in the first place.
+#
+# If the mailing list munges your emails, use:
+# git config sendemail.from '"Your Name" <your.email@example.com>'
+# the use of "" in that line will differ from the typically unquoted
+# 'git config user.name', which in turn is sufficient for 'git send-email'
+# to add an extra From: line in the body of your email that takes
+# precedence over any munged From: in the mail's headers.
+# See https://lists.openembedded.org/g/openembedded-core/message/166515
+# and https://lists.gnu.org/archive/html/qemu-devel/2023-09/msg06784.html
Ed Swierk <eswierk@skyportsystems.com> Ed Swierk via Qemu-devel <qemu-devel@nongnu.org>
Ian McKellar <ianloic@google.com> Ian McKellar via Qemu-devel <qemu-devel@nongnu.org>
Julia Suvorova <jusual@mail.ru> Julia Suvorova via Qemu-devel <qemu-devel@nongnu.org>
Justin Terry (VM) <juterry@microsoft.com> Justin Terry (VM) via Qemu-devel <qemu-devel@nongnu.org>
Stefan Weil <sw@weilnetz.de> Stefan Weil via <qemu-devel@nongnu.org>
+Andrey Drobyshev <andrey.drobyshev@virtuozzo.com> Andrey Drobyshev via <qemu-block@nongnu.org>
+BALATON Zoltan <balaton@eik.bme.hu> BALATON Zoltan via <qemu-ppc@nongnu.org>
# Next, replace old addresses by a more recent one.
Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> <aleksandar.markovic@mips.com>
diff --git a/.travis.yml b/.travis.yml
index b958eca..76859d4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -34,7 +34,7 @@ env:
- BASE_CONFIG="--disable-docs --disable-tools"
- TEST_BUILD_CMD=""
- TEST_CMD="make check V=1"
- # This is broadly a list of "mainline" softmmu targets which have support across the major distros
+ # This is broadly a list of "mainline" system targets which have support across the major distros
- MAIN_SOFTMMU_TARGETS="aarch64-softmmu,mips64-softmmu,ppc64-softmmu,riscv64-softmmu,s390x-softmmu,x86_64-softmmu"
- CCACHE_SLOPPINESS="include_file_ctime,include_file_mtime"
- CCACHE_MAXSIZE=1G
@@ -197,7 +197,7 @@ jobs:
$(exit $BUILD_RC);
fi
- - name: "[s390x] GCC (other-softmmu)"
+ - name: "[s390x] GCC (other-system)"
arch: s390x
dist: focal
addons:
diff --git a/MAINTAINERS b/MAINTAINERS
index ea91f9e..9e7dec4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -137,8 +137,8 @@ Overall TCG CPUs
M: Richard Henderson <richard.henderson@linaro.org>
R: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
-F: softmmu/cpus.c
-F: softmmu/watchpoint.c
+F: system/cpus.c
+F: system/watchpoint.c
F: cpu-common.c
F: cpu-target.c
F: page-vary-target.c
@@ -1229,6 +1229,9 @@ F: hw/misc/mac_via.c
F: hw/nubus/*
F: hw/display/macfb.c
F: hw/block/swim.c
+F: hw/misc/djmemc.c
+F: hw/misc/iosb.c
+F: hw/audio/asc.c
F: hw/m68k/bootinfo.h
F: include/standard-headers/asm-m68k/bootinfo.h
F: include/standard-headers/asm-m68k/bootinfo-mac.h
@@ -1238,6 +1241,9 @@ F: include/hw/display/macfb.h
F: include/hw/block/swim.h
F: include/hw/m68k/q800.h
F: include/hw/m68k/q800-glue.h
+F: include/hw/misc/djmemc.h
+F: include/hw/misc/iosb.h
+F: include/hw/audio/asc.h
virt
M: Laurent Vivier <laurent@vivier.eu>
@@ -2108,7 +2114,7 @@ S: Maintained
F: docs/interop/virtio-balloon-stats.rst
F: hw/virtio/virtio-balloon*.c
F: include/hw/virtio/virtio-balloon.h
-F: softmmu/balloon.c
+F: system/balloon.c
F: include/sysemu/balloon.h
virtio-9p
@@ -2795,7 +2801,7 @@ Device Tree
M: Alistair Francis <alistair.francis@wdc.com>
R: David Gibson <david@gibson.dropbear.id.au>
S: Maintained
-F: softmmu/device_tree.c
+F: system/device_tree.c
F: include/sysemu/device_tree.h
Dump
@@ -2851,11 +2857,11 @@ F: include/exec/memory.h
F: include/exec/ram_addr.h
F: include/exec/ramblock.h
F: include/sysemu/memory_mapping.h
-F: softmmu/dma-helpers.c
-F: softmmu/ioport.c
-F: softmmu/memory.c
-F: softmmu/memory_mapping.c
-F: softmmu/physmem.c
+F: system/dma-helpers.c
+F: system/ioport.c
+F: system/memory.c
+F: system/memory_mapping.c
+F: system/physmem.c
F: include/exec/memory-internal.h
F: scripts/coccinelle/memory-region-housekeeping.cocci
@@ -2908,12 +2914,12 @@ F: include/sysemu/runstate.h
F: include/sysemu/runstate-action.h
F: util/main-loop.c
F: util/qemu-timer.c
-F: softmmu/vl.c
-F: softmmu/main.c
-F: softmmu/cpus.c
-F: softmmu/cpu-throttle.c
-F: softmmu/cpu-timers.c
-F: softmmu/runstate*
+F: system/vl.c
+F: system/main.c
+F: system/cpus.c
+F: system/cpu-throttle.c
+F: system/cpu-timers.c
+F: system/runstate*
F: qapi/run-state.json
Read, Copy, Update (RCU)
@@ -3087,7 +3093,7 @@ F: qapi/qom.json
F: qapi/qdev.json
F: scripts/coccinelle/qom-parent-type.cocci
F: scripts/qom-cast-macro-clean-cocci-gen.py
-F: softmmu/qdev-monitor.c
+F: system/qdev-monitor.c
F: stubs/qdev.c
F: qom/
F: tests/unit/check-qom-interface.c
@@ -3121,7 +3127,7 @@ M: Thomas Huth <thuth@redhat.com>
M: Laurent Vivier <lvivier@redhat.com>
R: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
-F: softmmu/qtest.c
+F: system/qtest.c
F: accel/qtest/
F: tests/qtest/
F: docs/devel/qgraph.rst
@@ -3197,7 +3203,7 @@ F: scripts/simpletrace.py
TPM
M: Stefan Berger <stefanb@linux.ibm.com>
S: Maintained
-F: softmmu/tpm*
+F: system/tpm*
F: hw/tpm/*
F: include/hw/acpi/tpm.h
F: include/sysemu/tpm*
@@ -3242,7 +3248,7 @@ F: migration/rdma*
Migration dirty limit and dirty page rate
M: Hyman Huang <yong.huang@smartx.com>
S: Maintained
-F: softmmu/dirtylimit.c
+F: system/dirtylimit.c
F: include/sysemu/dirtylimit.h
F: migration/dirtyrate.c
F: migration/dirtyrate.h
@@ -3266,7 +3272,7 @@ F: scripts/xml-preprocess*
Seccomp
M: Daniel P. Berrange <berrange@redhat.com>
S: Odd Fixes
-F: softmmu/qemu-seccomp.c
+F: system/qemu-seccomp.c
F: include/sysemu/seccomp.h
F: tests/unit/test-seccomp.c
@@ -3685,7 +3691,7 @@ T: git https://github.com/stefanha/qemu.git block
Bootdevice
M: Gonglei <arei.gonglei@huawei.com>
S: Maintained
-F: softmmu/bootdevice.c
+F: system/bootdevice.c
Quorum
M: Alberto Garcia <berto@igalia.com>
diff --git a/accel/accel-softmmu.c b/accel/accel-system.c
index 9c804ba..fa8f437 100644
--- a/accel/accel-softmmu.c
+++ b/accel/accel-system.c
@@ -28,7 +28,7 @@
#include "hw/boards.h"
#include "sysemu/cpus.h"
#include "qemu/error-report.h"
-#include "accel-softmmu.h"
+#include "accel-system.h"
int accel_init_machine(AccelState *accel, MachineState *ms)
{
@@ -99,8 +99,8 @@ static const TypeInfo accel_ops_type_info = {
.class_size = sizeof(AccelOpsClass),
};
-static void accel_softmmu_register_types(void)
+static void accel_system_register_types(void)
{
type_register_static(&accel_ops_type_info);
}
-type_init(accel_softmmu_register_types);
+type_init(accel_system_register_types);
diff --git a/accel/accel-softmmu.h b/accel/accel-system.h
index 5e192f1..d41c62f 100644
--- a/accel/accel-softmmu.h
+++ b/accel/accel-system.h
@@ -7,9 +7,9 @@
* See the COPYING file in the top-level directory.
*/
-#ifndef ACCEL_SOFTMMU_H
-#define ACCEL_SOFTMMU_H
+#ifndef ACCEL_SYSTEM_H
+#define ACCEL_SYSTEM_H
void accel_init_ops_interfaces(AccelClass *ac);
-#endif /* ACCEL_SOFTMMU_H */
+#endif /* ACCEL_SYSTEM_H */
diff --git a/accel/accel-target.c b/accel/accel-target.c
index 11d74b4..7e3cbde 100644
--- a/accel/accel-target.c
+++ b/accel/accel-target.c
@@ -30,7 +30,7 @@
#include "hw/core/accel-cpu.h"
#ifndef CONFIG_USER_ONLY
-#include "accel-softmmu.h"
+#include "accel-system.h"
#endif /* !CONFIG_USER_ONLY */
static const TypeInfo accel_type = {
diff --git a/accel/meson.build b/accel/meson.build
index fda3157..5eaeb68 100644
--- a/accel/meson.build
+++ b/accel/meson.build
@@ -1,5 +1,5 @@
specific_ss.add(files('accel-target.c'))
-system_ss.add(files('accel-softmmu.c', 'accel-blocker.c'))
+system_ss.add(files('accel-system.c', 'accel-blocker.c'))
user_ss.add(files('accel-user.c'))
subdir('tcg')
diff --git a/accel/stubs/meson.build b/accel/stubs/meson.build
index 6b0f200..91a2d21 100644
--- a/accel/stubs/meson.build
+++ b/accel/stubs/meson.build
@@ -1,6 +1,6 @@
-sysemu_stubs_ss = ss.source_set()
-sysemu_stubs_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))
-sysemu_stubs_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
-sysemu_stubs_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c'))
+system_stubs_ss = ss.source_set()
+system_stubs_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))
+system_stubs_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
+system_stubs_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c'))
-specific_ss.add_all(when: ['CONFIG_SYSTEM_ONLY'], if_true: sysemu_stubs_ss)
+specific_ss.add_all(when: ['CONFIG_SYSTEM_ONLY'], if_true: system_stubs_ss)
diff --git a/accel/tcg/icount-common.c b/accel/tcg/icount-common.c
index 0bf5bb5..ec57192 100644
--- a/accel/tcg/icount-common.c
+++ b/accel/tcg/icount-common.c
@@ -37,7 +37,7 @@
#include "hw/core/cpu.h"
#include "sysemu/cpu-timers.h"
#include "sysemu/cpu-throttle.h"
-#include "softmmu/timers-state.h"
+#include "sysemu/cpu-timers-internal.h"
/*
* ICOUNT: Instruction Counter
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 5bf2761..68b252c 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -940,7 +940,7 @@ void *page_get_target_data(target_ulong address)
void page_reset_target_data(target_ulong start, target_ulong last) { }
#endif /* TARGET_PAGE_DATA_SIZE */
-/* The softmmu versions of these helpers are in cputlb.c. */
+/* The system-mode versions of these helpers are in cputlb.c. */
static void *cpu_mmu_lookup(CPUState *cpu, vaddr addr,
MemOp mop, uintptr_t ra, MMUAccessType type)
diff --git a/audio/audio.c b/audio/audio.c
index 730bf24..e9815d6 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -104,6 +104,7 @@ static audio_driver *audio_driver_lookup(const char *name)
static QTAILQ_HEAD(AudioStateHead, AudioState) audio_states =
QTAILQ_HEAD_INITIALIZER(audio_states);
+static AudioState *default_audio_state;
const struct mixeng_volume nominal_volume = {
.mute = 0,
@@ -1660,6 +1661,7 @@ static void free_audio_state(AudioState *s)
void audio_cleanup(void)
{
+ default_audio_state = NULL;
while (!QTAILQ_EMPTY(&audio_states)) {
AudioState *s = QTAILQ_FIRST(&audio_states);
QTAILQ_REMOVE(&audio_states, s, list);
@@ -1686,31 +1688,12 @@ static const VMStateDescription vmstate_audio = {
}
};
-static void audio_validate_opts(Audiodev *dev, Error **errp);
-
-static void audio_create_default_audiodevs(void)
+void audio_create_default_audiodevs(void)
{
- const char *drvname = getenv("QEMU_AUDIO_DRV");
-
- if (!defaults_enabled()) {
- return;
- }
-
- /* QEMU_AUDIO_DRV=none is used by libqtest. */
- if (drvname && !g_str_equal(drvname, "none")) {
- error_report("Please use -audiodev instead of QEMU_AUDIO_*");
- exit(1);
- }
-
for (int i = 0; audio_prio_list[i]; i++) {
- if (drvname && !g_str_equal(drvname, audio_prio_list[i])) {
- continue;
- }
-
if (audio_driver_lookup(audio_prio_list[i])) {
QDict *dict = qdict_new();
Audiodev *dev = NULL;
- AudiodevListEntry *e;
Visitor *v;
qdict_put_str(dict, "driver", audio_prio_list[i]);
@@ -1721,10 +1704,7 @@ static void audio_create_default_audiodevs(void)
visit_type_Audiodev(v, NULL, &dev, &error_fatal);
visit_free(v);
- audio_validate_opts(dev, &error_abort);
- e = g_new0(AudiodevListEntry, 1);
- e->dev = dev;
- QSIMPLEQ_INSERT_TAIL(&default_audiodevs, e, next);
+ audio_define_default(dev, &error_abort);
}
}
}
@@ -1770,6 +1750,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp)
goto out;
}
} else {
+ assert(!default_audio_state);
for (;;) {
AudiodevListEntry *e = QSIMPLEQ_FIRST(&default_audiodevs);
if (!e) {
@@ -1808,36 +1789,27 @@ out:
return NULL;
}
+AudioState *audio_get_default_audio_state(Error **errp)
+{
+ if (!default_audio_state) {
+ default_audio_state = audio_init(NULL, errp);
+ if (!default_audio_state) {
+ if (!QSIMPLEQ_EMPTY(&audiodevs)) {
+ error_append_hint(errp, "Perhaps you wanted to use -audio or set audiodev=%s?\n",
+ QSIMPLEQ_FIRST(&audiodevs)->dev->id);
+ }
+ }
+ }
+
+ return default_audio_state;
+}
+
bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp)
{
if (!card->state) {
- if (!QTAILQ_EMPTY(&audio_states)) {
- /*
- * FIXME: once it is possible to create an arbitrary
- * default device via -audio DRIVER,OPT=VALUE (no "model"),
- * replace this special case with the default AudioState*,
- * storing it in a separate global. For now, keep the
- * warning to encourage moving off magic use of the first
- * -audiodev.
- */
- if (QSIMPLEQ_EMPTY(&default_audiodevs)) {
- dolog("Device %s: audiodev default parameter is deprecated, please "
- "specify audiodev=%s\n", name,
- QTAILQ_FIRST(&audio_states)->dev->id);
- }
- card->state = QTAILQ_FIRST(&audio_states);
- } else {
- if (QSIMPLEQ_EMPTY(&default_audiodevs)) {
- audio_create_default_audiodevs();
- }
- card->state = audio_init(NULL, errp);
- if (!card->state) {
- if (!QSIMPLEQ_EMPTY(&audiodevs)) {
- error_append_hint(errp, "Perhaps you wanted to set audiodev=%s?",
- QSIMPLEQ_FIRST(&audiodevs)->dev->id);
- }
- return false;
- }
+ card->state = audio_get_default_audio_state(errp);
+ if (!card->state) {
+ return false;
}
}
@@ -2172,6 +2144,17 @@ void audio_define(Audiodev *dev)
QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next);
}
+void audio_define_default(Audiodev *dev, Error **errp)
+{
+ AudiodevListEntry *e;
+
+ audio_validate_opts(dev, errp);
+
+ e = g_new0(AudiodevListEntry, 1);
+ e->dev = dev;
+ QSIMPLEQ_INSERT_TAIL(&default_audiodevs, e, next);
+}
+
void audio_init_audiodevs(void)
{
AudiodevListEntry *e;
diff --git a/audio/audio.h b/audio/audio.h
index 80f3f92..fcc2230 100644
--- a/audio/audio.h
+++ b/audio/audio.h
@@ -169,11 +169,14 @@ void audio_sample_from_uint64(void *samples, int pos,
uint64_t left, uint64_t right);
void audio_define(Audiodev *audio);
+void audio_define_default(Audiodev *dev, Error **errp);
void audio_parse_option(const char *opt);
+void audio_create_default_audiodevs(void);
void audio_init_audiodevs(void);
void audio_help(void);
AudioState *audio_state_by_name(const char *name, Error **errp);
+AudioState *audio_get_default_audio_state(Error **errp);
const char *audio_get_id(QEMUSoundCard *card);
#define DEFINE_AUDIO_PROPERTIES(_s, _f) \
diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index 3f31852..c585828 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -549,7 +549,6 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as,
hw->size_emul);
hw->buf_emul = NULL;
} else {
- int err;
int trig = 0;
if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
diff --git a/block/nbd.c b/block/nbd.c
index 4a7f37d..52ebc8b 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -416,7 +416,8 @@ static void coroutine_fn GRAPH_RDLOCK nbd_reconnect_attempt(BDRVNBDState *s)
reconnect_delay_timer_del(s);
}
-static coroutine_fn int nbd_receive_replies(BDRVNBDState *s, uint64_t cookie)
+static coroutine_fn int nbd_receive_replies(BDRVNBDState *s, uint64_t cookie,
+ Error **errp)
{
int ret;
uint64_t ind = COOKIE_TO_INDEX(cookie), ind2;
@@ -457,20 +458,25 @@ static coroutine_fn int nbd_receive_replies(BDRVNBDState *s, uint64_t cookie)
/* We are under mutex and cookie is 0. We have to do the dirty work. */
assert(s->reply.cookie == 0);
- ret = nbd_receive_reply(s->bs, s->ioc, &s->reply, NULL);
- if (ret <= 0) {
- ret = ret ? ret : -EIO;
+ ret = nbd_receive_reply(s->bs, s->ioc, &s->reply, s->info.mode, errp);
+ if (ret == 0) {
+ ret = -EIO;
+ error_setg(errp, "server dropped connection");
+ }
+ if (ret < 0) {
nbd_channel_error(s, ret);
return ret;
}
if (nbd_reply_is_structured(&s->reply) &&
s->info.mode < NBD_MODE_STRUCTURED) {
nbd_channel_error(s, -EINVAL);
+ error_setg(errp, "unexpected structured reply");
return -EINVAL;
}
ind2 = COOKIE_TO_INDEX(s->reply.cookie);
if (ind2 >= MAX_NBD_REQUESTS || !s->requests[ind2].coroutine) {
nbd_channel_error(s, -EINVAL);
+ error_setg(errp, "unexpected cookie value");
return -EINVAL;
}
if (s->reply.cookie == cookie) {
@@ -609,13 +615,17 @@ static int nbd_parse_offset_hole_payload(BDRVNBDState *s,
*/
static int nbd_parse_blockstatus_payload(BDRVNBDState *s,
NBDStructuredReplyChunk *chunk,
- uint8_t *payload, uint64_t orig_length,
- NBDExtent32 *extent, Error **errp)
+ uint8_t *payload, bool wide,
+ uint64_t orig_length,
+ NBDExtent64 *extent, Error **errp)
{
uint32_t context_id;
+ uint32_t count;
+ size_t ext_len = wide ? sizeof(*extent) : sizeof(NBDExtent32);
+ size_t pay_len = sizeof(context_id) + wide * sizeof(count) + ext_len;
/* The server succeeded, so it must have sent [at least] one extent */
- if (chunk->length < sizeof(context_id) + sizeof(*extent)) {
+ if (chunk->length < pay_len) {
error_setg(errp, "Protocol error: invalid payload for "
"NBD_REPLY_TYPE_BLOCK_STATUS");
return -EINVAL;
@@ -630,8 +640,15 @@ static int nbd_parse_blockstatus_payload(BDRVNBDState *s,
return -EINVAL;
}
- extent->length = payload_advance32(&payload);
- extent->flags = payload_advance32(&payload);
+ if (wide) {
+ count = payload_advance32(&payload);
+ extent->length = payload_advance64(&payload);
+ extent->flags = payload_advance64(&payload);
+ } else {
+ count = 0;
+ extent->length = payload_advance32(&payload);
+ extent->flags = payload_advance32(&payload);
+ }
if (extent->length == 0) {
error_setg(errp, "Protocol error: server sent status chunk with "
@@ -652,7 +669,7 @@ static int nbd_parse_blockstatus_payload(BDRVNBDState *s,
* (always a safe status, even if it loses information).
*/
if (s->info.min_block && !QEMU_IS_ALIGNED(extent->length,
- s->info.min_block)) {
+ s->info.min_block)) {
trace_nbd_parse_blockstatus_compliance("extent length is unaligned");
if (extent->length > s->info.min_block) {
extent->length = QEMU_ALIGN_DOWN(extent->length,
@@ -666,13 +683,15 @@ static int nbd_parse_blockstatus_payload(BDRVNBDState *s,
/*
* We used NBD_CMD_FLAG_REQ_ONE, so the server should not have
* sent us any more than one extent, nor should it have included
- * status beyond our request in that extent. However, it's easy
- * enough to ignore the server's noncompliance without killing the
+ * status beyond our request in that extent. Furthermore, a wide
+ * server should have replied with an accurate count (we left
+ * count at 0 for a narrow server). However, it's easy enough to
+ * ignore the server's noncompliance without killing the
* connection; just ignore trailing extents, and clamp things to
* the length of our request.
*/
- if (chunk->length > sizeof(context_id) + sizeof(*extent)) {
- trace_nbd_parse_blockstatus_compliance("more than one extent");
+ if (count != wide || chunk->length > pay_len) {
+ trace_nbd_parse_blockstatus_compliance("unexpected extent count");
}
if (extent->length > orig_length) {
extent->length = orig_length;
@@ -842,9 +861,9 @@ static coroutine_fn int nbd_co_do_receive_one_chunk(
}
*request_ret = 0;
- ret = nbd_receive_replies(s, cookie);
+ ret = nbd_receive_replies(s, cookie, errp);
if (ret < 0) {
- error_setg(errp, "Connection closed");
+ error_prepend(errp, "Connection closed: ");
return -EIO;
}
assert(s->ioc);
@@ -1118,7 +1137,7 @@ nbd_co_receive_cmdread_reply(BDRVNBDState *s, uint64_t cookie,
static int coroutine_fn
nbd_co_receive_blockstatus_reply(BDRVNBDState *s, uint64_t cookie,
- uint64_t length, NBDExtent32 *extent,
+ uint64_t length, NBDExtent64 *extent,
int *request_ret, Error **errp)
{
NBDReplyChunkIter iter;
@@ -1131,11 +1150,17 @@ nbd_co_receive_blockstatus_reply(BDRVNBDState *s, uint64_t cookie,
NBD_FOREACH_REPLY_CHUNK(s, iter, cookie, false, NULL, &reply, &payload) {
int ret;
NBDStructuredReplyChunk *chunk = &reply.structured;
+ bool wide;
assert(nbd_reply_is_structured(&reply));
switch (chunk->type) {
+ case NBD_REPLY_TYPE_BLOCK_STATUS_EXT:
case NBD_REPLY_TYPE_BLOCK_STATUS:
+ wide = chunk->type == NBD_REPLY_TYPE_BLOCK_STATUS_EXT;
+ if ((s->info.mode >= NBD_MODE_EXTENDED) != wide) {
+ trace_nbd_extended_headers_compliance("block_status");
+ }
if (received) {
nbd_channel_error(s, -EINVAL);
error_setg(&local_err, "Several BLOCK_STATUS chunks in reply");
@@ -1143,9 +1168,9 @@ nbd_co_receive_blockstatus_reply(BDRVNBDState *s, uint64_t cookie,
}
received = true;
- ret = nbd_parse_blockstatus_payload(s, &reply.structured,
- payload, length, extent,
- &local_err);
+ ret = nbd_parse_blockstatus_payload(
+ s, &reply.structured, payload, wide,
+ length, extent, &local_err);
if (ret < 0) {
nbd_channel_error(s, ret);
nbd_iter_channel_error(&iter, ret, &local_err);
@@ -1375,7 +1400,7 @@ static int coroutine_fn GRAPH_RDLOCK nbd_client_co_block_status(
int64_t *pnum, int64_t *map, BlockDriverState **file)
{
int ret, request_ret;
- NBDExtent32 extent = { 0 };
+ NBDExtent64 extent = { 0 };
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
Error *local_err = NULL;
diff --git a/block/trace-events b/block/trace-events
index 925aa55..8e789e1 100644
--- a/block/trace-events
+++ b/block/trace-events
@@ -166,6 +166,7 @@ iscsi_xcopy(void *src_lun, uint64_t src_off, void *dst_lun, uint64_t dst_off, ui
# nbd.c
nbd_parse_blockstatus_compliance(const char *err) "ignoring extra data from non-compliant server: %s"
nbd_structured_read_compliance(const char *type) "server sent non-compliant unaligned read %s chunk"
+nbd_extended_headers_compliance(const char *type) "server sent non-compliant %s chunk not matching choice of extended headers"
nbd_read_reply_entry_fail(int ret, const char *err) "ret = %d, err: %s"
nbd_co_request_fail(uint64_t from, uint64_t len, uint64_t handle, uint16_t flags, uint16_t type, const char *name, int ret, const char *err) "Request failed { .from = %" PRIu64", .len = %" PRIu64 ", .handle = %" PRIu64 ", .flags = 0x%" PRIx16 ", .type = %" PRIu16 " (%s) } ret = %d, err: %s"
nbd_client_handshake(const char *export_name) "export '%s'"
diff --git a/configure b/configure
index e081270..97a5e8d 100755
--- a/configure
+++ b/configure
@@ -252,7 +252,7 @@ docs="auto"
EXESUF=""
prefix="/usr/local"
qemu_suffix="qemu"
-softmmu="yes"
+system="yes"
linux_user=""
bsd_user=""
plugins="$default_feature"
@@ -740,9 +740,9 @@ for opt do
;;
--enable-tcg) tcg="enabled"
;;
- --disable-system) softmmu="no"
+ --disable-system) system="no"
;;
- --enable-system) softmmu="yes"
+ --enable-system) system="yes"
;;
--disable-user)
linux_user="no" ;
@@ -864,7 +864,7 @@ else
error_exit "user mode emulation not supported on this architecture"
fi
fi
-if [ "$softmmu" = "yes" ]; then
+if [ "$system" = "yes" ]; then
mak_wilds="${mak_wilds} $source_path/configs/targets/*-softmmu.mak"
fi
@@ -1756,7 +1756,7 @@ for target in $target_list; do
case $target in
xtensa*-linux-user)
- # the toolchain is not complete with headers, only build softmmu tests
+ # the toolchain is not complete with headers, only build system tests
continue
;;
*-softmmu)
diff --git a/cpu-target.c b/cpu-target.c
index 658d179..79363ae 100644
--- a/cpu-target.c
+++ b/cpu-target.c
@@ -202,7 +202,7 @@ static Property cpu_common_props[] = {
prctl_unalign_sigbus, false),
#else
/*
- * Create a memory property for softmmu CPU object, so users can
+ * Create a memory property for system CPU object, so users can
* wire up its memory. The default if no link is set up is to use
* the system address space.
*/
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 3b074b9..8b13632 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -23,12 +23,6 @@ deprecated.
System emulator command line arguments
--------------------------------------
-Creating sound card devices without ``audiodev=`` property (since 4.2)
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
-
-When not using the deprecated legacy audio config, each sound card
-should specify an ``audiodev=`` property.
-
Short-form boolean options (since 6.0)
''''''''''''''''''''''''''''''''''''''
diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst
index e83ed08..f040369 100644
--- a/docs/about/removed-features.rst
+++ b/docs/about/removed-features.rst
@@ -442,11 +442,23 @@ line using a ``secret`` object instance.
The ``-audiodev`` and ``-audio`` command line options are now the only
way to specify audio backend settings.
-Creating vnc without ``audiodev=`` property (removed in 8.2)
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
-
-When using vnc, you should specify an ``audiodev=`` property if
-you plan to transmit audio through the VNC protocol.
+Using ``-audiodev`` to define the default audio backend (removed in 8.2)
+''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+
+If no audiodev property is specified, previous versions would use the
+first ``-audiodev`` command line option as a fallback. Starting with
+version 8.2, audio backends created with ``-audiodev`` will only be
+used by clients (sound cards, machines with embedded sound hardware, VNC)
+that refer to it in an ``audiodev=`` property.
+
+In order to configure a default audio backend, use the ``-audio``
+command line option without specifying a ``model``; while previous
+versions of QEMU required a model, starting with version 8.2
+QEMU does not require a model and will not create any sound card
+in this case.
+
+Note that the default audio backend must be configured on the command
+line if the ``-nodefaults`` options is used.
QEMU Machine Protocol (QMP) commands
------------------------------------
diff --git a/docs/devel/build-system.rst b/docs/devel/build-system.rst
index 0f990bb..21f78da 100644
--- a/docs/devel/build-system.rst
+++ b/docs/devel/build-system.rst
@@ -225,14 +225,14 @@ Target-dependent emulator sourcesets:
The sourceset is only used for system emulators.
Each subdirectory in ``target/`` instead should add one sourceset to each
- of the ``target_arch`` and ``target_softmmu_arch``, which are used respectively
+ of the ``target_arch`` and ``target_system_arch``, which are used respectively
for all emulators and for system emulators only. For example::
arm_ss = ss.source_set()
arm_system_ss = ss.source_set()
...
target_arch += {'arm': arm_ss}
- target_softmmu_arch += {'arm': arm_system_ss}
+ target_system_arch += {'arm': arm_system_ss}
Module sourcesets:
There are two dictionaries for modules: ``modules`` is used for
diff --git a/docs/devel/qtest.rst b/docs/devel/qtest.rst
index 0455aa0..c5b8546 100644
--- a/docs/devel/qtest.rst
+++ b/docs/devel/qtest.rst
@@ -81,7 +81,7 @@ which you can run manually.
QTest Protocol
--------------
-.. kernel-doc:: softmmu/qtest.c
+.. kernel-doc:: system/qtest.c
:doc: QTest Protocol
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
index 5d1fc0a..f3e2472 100644
--- a/docs/devel/testing.rst
+++ b/docs/devel/testing.rst
@@ -1458,7 +1458,7 @@ TCG test dependencies
~~~~~~~~~~~~~~~~~~~~~
The TCG tests are deliberately very light on dependencies and are
-either totally bare with minimal gcc lib support (for softmmu tests)
+either totally bare with minimal gcc lib support (for system-mode tests)
or just glibc (for linux-user tests). This is because getting a cross
compiler to work with additional libraries can be challenging.
diff --git a/docs/interop/nbd.txt b/docs/interop/nbd.txt
index f5ca251..18efb25 100644
--- a/docs/interop/nbd.txt
+++ b/docs/interop/nbd.txt
@@ -69,3 +69,4 @@ NBD_CMD_BLOCK_STATUS for "qemu:dirty-bitmap:", NBD_CMD_CACHE
NBD_CMD_FLAG_FAST_ZERO
* 5.2: NBD_CMD_BLOCK_STATUS for "qemu:allocation-depth"
* 7.1: NBD_FLAG_CAN_MULTI_CONN for shareable writable exports
+* 8.2: NBD_OPT_EXTENDED_HEADERS, NBD_FLAG_BLOCK_STATUS_PAYLOAD
diff --git a/dump/dump.c b/dump/dump.c
index d4ef713..d3578dd 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -1872,20 +1872,20 @@ static void dump_init(DumpState *s, int fd, bool has_format,
if (vmci) {
uint64_t addr, note_head_size, name_size, desc_size;
uint32_t size;
- uint16_t format;
+ uint16_t guest_format;
note_head_size = dump_is_64bit(s) ?
sizeof(Elf64_Nhdr) : sizeof(Elf32_Nhdr);
- format = le16_to_cpu(vmci->vmcoreinfo.guest_format);
+ guest_format = le16_to_cpu(vmci->vmcoreinfo.guest_format);
size = le32_to_cpu(vmci->vmcoreinfo.size);
addr = le64_to_cpu(vmci->vmcoreinfo.paddr);
if (!vmci->has_vmcoreinfo) {
warn_report("guest note is not present");
} else if (size < note_head_size || size > MAX_GUEST_NOTE_SIZE) {
warn_report("guest note size is invalid: %" PRIu32, size);
- } else if (format != FW_CFG_VMCOREINFO_FORMAT_ELF) {
- warn_report("guest note format is unsupported: %" PRIu16, format);
+ } else if (guest_format != FW_CFG_VMCOREINFO_FORMAT_ELF) {
+ warn_report("guest note format is unsupported: %" PRIu16, guest_format);
} else {
s->guest_note = g_malloc(size + 1); /* +1 for adding \0 */
cpu_physical_memory_read(addr, s->guest_note, size);
diff --git a/gdbstub/internals.h b/gdbstub/internals.h
index fee2430..f7fd1be 100644
--- a/gdbstub/internals.h
+++ b/gdbstub/internals.h
@@ -103,7 +103,7 @@ static inline int tohex(int v)
}
/*
- * Connection helpers for both softmmu and user backends
+ * Connection helpers for both system and user backends
*/
void gdb_put_strbuf(void);
@@ -229,7 +229,7 @@ void gdb_breakpoint_remove_all(CPUState *cs);
* @is_write: is it a write operation
*
* This function is specialised depending on the mode we are running
- * in. For softmmu guests we can switch the interpretation of the
+ * in. For system guests we can switch the interpretation of the
* address to a physical address.
*/
int gdb_target_memory_rw_debug(CPUState *cs, hwaddr addr,
diff --git a/gdbstub/meson.build b/gdbstub/meson.build
index a5a1f4e..e5bccba 100644
--- a/gdbstub/meson.build
+++ b/gdbstub/meson.build
@@ -1,6 +1,6 @@
#
# The main gdbstub still relies on per-build definitions of various
-# types. The bits pushed to softmmu/user.c try to use guest agnostic
+# types. The bits pushed to system/user.c try to use guest agnostic
# types such as hwaddr.
#
@@ -12,7 +12,7 @@ gdb_system_ss = ss.source_set()
# We build two versions of gdbstub, one for each mode
gdb_user_ss.add(files('gdbstub.c', 'user.c'))
-gdb_system_ss.add(files('gdbstub.c', 'softmmu.c'))
+gdb_system_ss.add(files('gdbstub.c', 'system.c'))
gdb_user_ss = gdb_user_ss.apply(config_targetos, strict: false)
gdb_system_ss = gdb_system_ss.apply(config_targetos, strict: false)
@@ -23,15 +23,15 @@ libgdb_user = static_library('gdb_user',
c_args: '-DCONFIG_USER_ONLY',
build_by_default: false)
-libgdb_softmmu = static_library('gdb_softmmu',
+libgdb_system = static_library('gdb_system',
gdb_system_ss.sources() + genh,
name_suffix: 'fa',
build_by_default: false)
gdb_user = declare_dependency(link_whole: libgdb_user)
user_ss.add(gdb_user)
-gdb_softmmu = declare_dependency(link_whole: libgdb_softmmu)
-system_ss.add(gdb_softmmu)
+gdb_system = declare_dependency(link_whole: libgdb_system)
+system_ss.add(gdb_system)
common_ss.add(files('syscalls.c'))
diff --git a/gdbstub/softmmu.c b/gdbstub/system.c
index 9f0b8b5..189975b 100644
--- a/gdbstub/softmmu.c
+++ b/gdbstub/system.c
@@ -104,7 +104,7 @@ static void gdb_chr_event(void *opaque, QEMUChrEvent event)
}
/*
- * In softmmu mode we stop the VM and wait to send the syscall packet
+ * In system-mode we stop the VM and wait to send the syscall packet
* until notification that the CPU has stopped. This must be done
* because if the packet is sent now the reply from the syscall
* request could be received while the CPU is still in the running
diff --git a/gdbstub/trace-events b/gdbstub/trace-events
index 7bc79a7..4fd126a 100644
--- a/gdbstub/trace-events
+++ b/gdbstub/trace-events
@@ -28,5 +28,5 @@ gdbstub_err_checksum_invalid(uint8_t ch) "got invalid command checksum digit: 0x
gdbstub_err_checksum_incorrect(uint8_t expected, uint8_t got) "got command packet with incorrect checksum, expected=0x%02x, received=0x%02x"
gdbstub_err_unexpected_runpkt(uint8_t ch) "unexpected packet (0x%02x) while target running"
-# softmmu.c
+# system.c
gdbstub_hit_watchpoint(const char *type, int cpu_gdb_index, uint64_t vaddr) "Watchpoint hit, type=\"%s\" cpu=%d, vaddr=0x%" PRIx64 ""
diff --git a/hw/audio/Kconfig b/hw/audio/Kconfig
index e76c69c..d099351 100644
--- a/hw/audio/Kconfig
+++ b/hw/audio/Kconfig
@@ -47,3 +47,6 @@ config PL041
config CS4231
bool
+
+config ASC
+ bool
diff --git a/hw/audio/asc.c b/hw/audio/asc.c
new file mode 100644
index 0000000..0f36b4c
--- /dev/null
+++ b/hw/audio/asc.c
@@ -0,0 +1,727 @@
+/*
+ * QEMU Apple Sound Chip emulation
+ *
+ * Apple Sound Chip (ASC) 344S0063
+ * Enhanced Apple Sound Chip (EASC) 343S1063
+ *
+ * Copyright (c) 2012-2018 Laurent Vivier <laurent@vivier.eu>
+ * Copyright (c) 2022 Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/timer.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "audio/audio.h"
+#include "hw/audio/asc.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+/*
+ * Linux doesn't provide information about ASC, see arch/m68k/mac/macboing.c
+ * and arch/m68k/include/asm/mac_asc.h
+ *
+ * best information is coming from MAME:
+ * https://github.com/mamedev/mame/blob/master/src/devices/sound/asc.h
+ * https://github.com/mamedev/mame/blob/master/src/devices/sound/asc.cpp
+ * Emulation by R. Belmont
+ * or MESS:
+ * http://mess.redump.net/mess/driver_info/easc
+ *
+ * 0x800: VERSION
+ * 0x801: MODE
+ * 1=FIFO mode,
+ * 2=wavetable mode
+ * 0x802: CONTROL
+ * bit 0=analog or PWM output,
+ * 1=stereo/mono,
+ * 7=processing time exceeded
+ * 0x803: FIFO MODE
+ * bit 7=clear FIFO,
+ * bit 1="non-ROM companding",
+ * bit 0="ROM companding")
+ * 0x804: FIFO IRQ STATUS
+ * bit 0=ch A 1/2 full,
+ * 1=ch A full,
+ * 2=ch B 1/2 full,
+ * 3=ch B full)
+ * 0x805: WAVETABLE CONTROL
+ * bits 0-3 wavetables 0-3 start
+ * 0x806: VOLUME
+ * bits 2-4 = 3 bit internal ASC volume,
+ * bits 5-7 = volume control sent to Sony sound chip
+ * 0x807: CLOCK RATE
+ * 0 = Mac 22257 Hz,
+ * 1 = undefined,
+ * 2 = 22050 Hz,
+ * 3 = 44100 Hz
+ * 0x80a: PLAY REC A
+ * 0x80f: TEST
+ * bits 6-7 = digital test,
+ * bits 4-5 = analog test
+ * 0x810: WAVETABLE 0 PHASE
+ * big-endian 9.15 fixed-point, only 24 bits valid
+ * 0x814: WAVETABLE 0 INCREMENT
+ * big-endian 9.15 fixed-point, only 24 bits valid
+ * 0x818: WAVETABLE 1 PHASE
+ * 0x81C: WAVETABLE 1 INCREMENT
+ * 0x820: WAVETABLE 2 PHASE
+ * 0x824: WAVETABLE 2 INCREMENT
+ * 0x828: WAVETABLE 3 PHASE
+ * 0x82C: WAVETABLE 3 INCREMENT
+ * 0x830: UNKNOWN START
+ * NetBSD writes Wavetable data here (are there more
+ * wavetables/channels than we know about?)
+ * 0x857: UNKNOWN END
+ */
+
+#define ASC_SIZE 0x2000
+
+enum {
+ ASC_VERSION = 0x00,
+ ASC_MODE = 0x01,
+ ASC_CONTROL = 0x02,
+ ASC_FIFOMODE = 0x03,
+ ASC_FIFOIRQ = 0x04,
+ ASC_WAVECTRL = 0x05,
+ ASC_VOLUME = 0x06,
+ ASC_CLOCK = 0x07,
+ ASC_PLAYRECA = 0x0a,
+ ASC_TEST = 0x0f,
+ ASC_WAVETABLE = 0x10
+};
+
+#define ASC_FIFO_STATUS_HALF_FULL 1
+#define ASC_FIFO_STATUS_FULL_EMPTY 2
+
+#define ASC_EXTREGS_FIFOCTRL 0x8
+#define ASC_EXTREGS_INTCTRL 0x9
+#define ASC_EXTREGS_CDXA_DECOMP_FILT 0x10
+
+#define ASC_FIFO_CYCLE_TIME ((NANOSECONDS_PER_SECOND / ASC_FREQ) * \
+ 0x400)
+
+static void asc_raise_irq(ASCState *s)
+{
+ qemu_set_irq(s->irq, 1);
+}
+
+static void asc_lower_irq(ASCState *s)
+{
+ qemu_set_irq(s->irq, 0);
+}
+
+static uint8_t asc_fifo_get(ASCFIFOState *fs)
+{
+ ASCState *s = container_of(fs, ASCState, fifos[fs->index]);
+ bool fifo_half_irq_enabled = fs->extregs[ASC_EXTREGS_INTCTRL] & 1;
+ uint8_t val;
+
+ assert(fs->cnt);
+
+ val = fs->fifo[fs->rptr];
+ trace_asc_fifo_get('A' + fs->index, fs->rptr, fs->cnt, val);
+
+ fs->rptr++;
+ fs->rptr &= 0x3ff;
+ fs->cnt--;
+
+ if (fs->cnt <= 0x1ff) {
+ /* FIFO less than half full */
+ fs->int_status |= ASC_FIFO_STATUS_HALF_FULL;
+ } else {
+ /* FIFO more than half full */
+ fs->int_status &= ~ASC_FIFO_STATUS_HALF_FULL;
+ }
+
+ if (fs->cnt == 0x1ff && fifo_half_irq_enabled) {
+ /* Raise FIFO half full IRQ */
+ asc_raise_irq(s);
+ }
+
+ if (fs->cnt == 0) {
+ /* Raise FIFO empty IRQ */
+ fs->int_status |= ASC_FIFO_STATUS_FULL_EMPTY;
+ asc_raise_irq(s);
+ }
+
+ return val;
+}
+
+static int generate_fifo(ASCState *s, int maxsamples)
+{
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ uint8_t *buf = s->mixbuf;
+ int i, wcount = 0;
+
+ while (wcount < maxsamples) {
+ uint8_t val;
+ int16_t d, f0, f1;
+ int32_t t;
+ int shift, filter;
+ bool hasdata = false;
+
+ for (i = 0; i < 2; i++) {
+ ASCFIFOState *fs = &s->fifos[i];
+
+ switch (fs->extregs[ASC_EXTREGS_FIFOCTRL] & 0x83) {
+ case 0x82:
+ /*
+ * CD-XA BRR mode: decompress 15 bytes into 28 16-bit
+ * samples
+ */
+ if (!fs->cnt) {
+ val = 0x80;
+ break;
+ }
+
+ if (fs->xa_cnt == -1) {
+ /* Start of packet, get flags */
+ fs->xa_flags = asc_fifo_get(fs);
+ fs->xa_cnt = 0;
+ }
+
+ shift = fs->xa_flags & 0xf;
+ filter = fs->xa_flags >> 4;
+ f0 = (int8_t)fs->extregs[ASC_EXTREGS_CDXA_DECOMP_FILT +
+ (filter << 1) + 1];
+ f1 = (int8_t)fs->extregs[ASC_EXTREGS_CDXA_DECOMP_FILT +
+ (filter << 1)];
+
+ if ((fs->xa_cnt & 1) == 0) {
+ if (!fs->cnt) {
+ val = 0x80;
+ break;
+ }
+
+ fs->xa_val = asc_fifo_get(fs);
+ d = (fs->xa_val & 0xf) << 12;
+ } else {
+ d = (fs->xa_val & 0xf0) << 8;
+ }
+ t = (d >> shift) + (((fs->xa_last[0] * f0) +
+ (fs->xa_last[1] * f1) + 32) >> 6);
+ if (t < -32768) {
+ t = -32768;
+ } else if (t > 32767) {
+ t = 32767;
+ }
+
+ /*
+ * CD-XA BRR generates 16-bit signed output, so convert to
+ * 8-bit before writing to buffer. Does real hardware do the
+ * same?
+ */
+ val = (uint8_t)(t / 256) ^ 0x80;
+ hasdata = true;
+ fs->xa_cnt++;
+
+ fs->xa_last[1] = fs->xa_last[0];
+ fs->xa_last[0] = (int16_t)t;
+
+ if (fs->xa_cnt == 28) {
+ /* End of packet */
+ fs->xa_cnt = -1;
+ }
+ break;
+
+ default:
+ /* fallthrough */
+ case 0x80:
+ /* Raw mode */
+ if (fs->cnt) {
+ val = asc_fifo_get(fs);
+ hasdata = true;
+ } else {
+ val = 0x80;
+ }
+ break;
+ }
+
+ buf[wcount * 2 + i] = val;
+ }
+
+ if (!hasdata) {
+ break;
+ }
+
+ wcount++;
+ }
+
+ /*
+ * MacOS (un)helpfully leaves the FIFO engine running even when it has
+ * finished writing out samples, but still expects the FIFO empty
+ * interrupts to be generated for each FIFO cycle (without these interrupts
+ * MacOS will freeze)
+ */
+ if (s->fifos[0].cnt == 0 && s->fifos[1].cnt == 0) {
+ if (!s->fifo_empty_ns) {
+ /* FIFO has completed first empty cycle */
+ s->fifo_empty_ns = now;
+ } else if (now > (s->fifo_empty_ns + ASC_FIFO_CYCLE_TIME)) {
+ /* FIFO has completed entire cycle with no data */
+ s->fifos[0].int_status |= ASC_FIFO_STATUS_HALF_FULL |
+ ASC_FIFO_STATUS_FULL_EMPTY;
+ s->fifos[1].int_status |= ASC_FIFO_STATUS_HALF_FULL |
+ ASC_FIFO_STATUS_FULL_EMPTY;
+ s->fifo_empty_ns = now;
+ asc_raise_irq(s);
+ }
+ } else {
+ /* FIFO contains data, reset empty time */
+ s->fifo_empty_ns = 0;
+ }
+
+ return wcount;
+}
+
+static int generate_wavetable(ASCState *s, int maxsamples)
+{
+ uint8_t *buf = s->mixbuf;
+ int channel, count = 0;
+
+ while (count < maxsamples) {
+ uint32_t left = 0, right = 0;
+ uint8_t sample;
+
+ for (channel = 0; channel < 4; channel++) {
+ ASCFIFOState *fs = &s->fifos[channel >> 1];
+ int chanreg = ASC_WAVETABLE + (channel << 3);
+ uint32_t phase, incr, offset;
+
+ phase = ldl_be_p(&s->regs[chanreg]);
+ incr = ldl_be_p(&s->regs[chanreg + sizeof(uint32_t)]);
+
+ phase += incr;
+ offset = (phase >> 15) & 0x1ff;
+ sample = fs->fifo[0x200 * (channel >> 1) + offset];
+
+ stl_be_p(&s->regs[chanreg], phase);
+
+ left += sample;
+ right += sample;
+ }
+
+ buf[count * 2] = left >> 2;
+ buf[count * 2 + 1] = right >> 2;
+
+ count++;
+ }
+
+ return count;
+}
+
+static void asc_out_cb(void *opaque, int free_b)
+{
+ ASCState *s = opaque;
+ int samples, generated;
+
+ if (free_b == 0) {
+ return;
+ }
+
+ samples = MIN(s->samples, free_b >> s->shift);
+
+ switch (s->regs[ASC_MODE] & 3) {
+ default:
+ /* Off */
+ generated = 0;
+ break;
+ case 1:
+ /* FIFO mode */
+ generated = generate_fifo(s, samples);
+ break;
+ case 2:
+ /* Wave table mode */
+ generated = generate_wavetable(s, samples);
+ break;
+ }
+
+ if (!generated) {
+ /* Workaround for audio underflow bug on Windows dsound backend */
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ int silent_samples = muldiv64(now - s->fifo_empty_ns,
+ NANOSECONDS_PER_SECOND, ASC_FREQ);
+
+ if (silent_samples > ASC_FIFO_CYCLE_TIME / 2) {
+ /*
+ * No new FIFO data within half a cycle time (~23ms) so fill the
+ * entire available buffer with silence. This prevents an issue
+ * with the Windows dsound backend whereby the sound appears to
+ * loop because the FIFO has run out of data, and the driver
+ * reuses the stale content in its circular audio buffer.
+ */
+ AUD_write(s->voice, s->silentbuf, samples << s->shift);
+ }
+ return;
+ }
+
+ AUD_write(s->voice, s->mixbuf, generated << s->shift);
+}
+
+static uint64_t asc_fifo_read(void *opaque, hwaddr addr,
+ unsigned size)
+{
+ ASCFIFOState *fs = opaque;
+
+ trace_asc_read_fifo('A' + fs->index, addr, size, fs->fifo[addr]);
+ return fs->fifo[addr];
+}
+
+static void asc_fifo_write(void *opaque, hwaddr addr, uint64_t value,
+ unsigned size)
+{
+ ASCFIFOState *fs = opaque;
+ ASCState *s = container_of(fs, ASCState, fifos[fs->index]);
+ bool fifo_half_irq_enabled = fs->extregs[ASC_EXTREGS_INTCTRL] & 1;
+
+ trace_asc_write_fifo('A' + fs->index, addr, size, fs->wptr, fs->cnt, value);
+
+ if (s->regs[ASC_MODE] == 1) {
+ fs->fifo[fs->wptr++] = value;
+ fs->wptr &= 0x3ff;
+ fs->cnt++;
+
+ if (fs->cnt <= 0x1ff) {
+ /* FIFO less than half full */
+ fs->int_status |= ASC_FIFO_STATUS_HALF_FULL;
+ } else {
+ /* FIFO at least half full */
+ fs->int_status &= ~ASC_FIFO_STATUS_HALF_FULL;
+ }
+
+ if (fs->cnt == 0x200 && fifo_half_irq_enabled) {
+ /* Raise FIFO half full interrupt */
+ asc_raise_irq(s);
+ }
+
+ if (fs->cnt == 0x3ff) {
+ /* Raise FIFO full interrupt */
+ fs->int_status |= ASC_FIFO_STATUS_FULL_EMPTY;
+ asc_raise_irq(s);
+ }
+ } else {
+ fs->fifo[addr] = value;
+ }
+ return;
+}
+
+static const MemoryRegionOps asc_fifo_ops = {
+ .read = asc_fifo_read,
+ .write = asc_fifo_write,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void asc_fifo_reset(ASCFIFOState *fs);
+
+static uint64_t asc_read(void *opaque, hwaddr addr,
+ unsigned size)
+{
+ ASCState *s = opaque;
+ uint64_t prev, value;
+
+ switch (addr) {
+ case ASC_VERSION:
+ switch (s->type) {
+ default:
+ case ASC_TYPE_ASC:
+ value = 0;
+ break;
+ case ASC_TYPE_EASC:
+ value = 0xb0;
+ break;
+ }
+ break;
+ case ASC_FIFOIRQ:
+ prev = (s->fifos[0].int_status & 0x3) |
+ (s->fifos[1].int_status & 0x3) << 2;
+
+ s->fifos[0].int_status = 0;
+ s->fifos[1].int_status = 0;
+ asc_lower_irq(s);
+ value = prev;
+ break;
+ default:
+ value = s->regs[addr];
+ break;
+ }
+
+ trace_asc_read_reg(addr, size, value);
+ return value;
+}
+
+static void asc_write(void *opaque, hwaddr addr, uint64_t value,
+ unsigned size)
+{
+ ASCState *s = opaque;
+
+ switch (addr) {
+ case ASC_MODE:
+ value &= 3;
+ if (value != s->regs[ASC_MODE]) {
+ asc_fifo_reset(&s->fifos[0]);
+ asc_fifo_reset(&s->fifos[1]);
+ asc_lower_irq(s);
+ if (value != 0) {
+ AUD_set_active_out(s->voice, 1);
+ } else {
+ AUD_set_active_out(s->voice, 0);
+ }
+ }
+ break;
+ case ASC_FIFOMODE:
+ if (value & 0x80) {
+ asc_fifo_reset(&s->fifos[0]);
+ asc_fifo_reset(&s->fifos[1]);
+ asc_lower_irq(s);
+ }
+ break;
+ case ASC_WAVECTRL:
+ break;
+ case ASC_VOLUME:
+ {
+ int vol = (value & 0xe0);
+
+ AUD_set_volume_out(s->voice, 0, vol, vol);
+ break;
+ }
+ }
+
+ trace_asc_write_reg(addr, size, value);
+ s->regs[addr] = value;
+}
+
+static const MemoryRegionOps asc_regs_ops = {
+ .read = asc_read,
+ .write = asc_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ }
+};
+
+static uint64_t asc_ext_read(void *opaque, hwaddr addr,
+ unsigned size)
+{
+ ASCFIFOState *fs = opaque;
+ uint64_t value;
+
+ value = fs->extregs[addr];
+
+ trace_asc_read_extreg('A' + fs->index, addr, size, value);
+ return value;
+}
+
+static void asc_ext_write(void *opaque, hwaddr addr, uint64_t value,
+ unsigned size)
+{
+ ASCFIFOState *fs = opaque;
+
+ trace_asc_write_extreg('A' + fs->index, addr, size, value);
+
+ fs->extregs[addr] = value;
+}
+
+static const MemoryRegionOps asc_extregs_ops = {
+ .read = asc_ext_read,
+ .write = asc_ext_write,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static int asc_post_load(void *opaque, int version)
+{
+ ASCState *s = ASC(opaque);
+
+ if (s->regs[ASC_MODE] != 0) {
+ AUD_set_active_out(s->voice, 1);
+ }
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_asc_fifo = {
+ .name = "apple-sound-chip.fifo",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8_ARRAY(fifo, ASCFIFOState, ASC_FIFO_SIZE),
+ VMSTATE_UINT8(int_status, ASCFIFOState),
+ VMSTATE_INT32(cnt, ASCFIFOState),
+ VMSTATE_INT32(wptr, ASCFIFOState),
+ VMSTATE_INT32(rptr, ASCFIFOState),
+ VMSTATE_UINT8_ARRAY(extregs, ASCFIFOState, ASC_EXTREG_SIZE),
+ VMSTATE_INT32(xa_cnt, ASCFIFOState),
+ VMSTATE_UINT8(xa_val, ASCFIFOState),
+ VMSTATE_UINT8(xa_flags, ASCFIFOState),
+ VMSTATE_INT16_ARRAY(xa_last, ASCFIFOState, 2),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_asc = {
+ .name = "apple-sound-chip",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .post_load = asc_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT_ARRAY(fifos, ASCState, 2, 0, vmstate_asc_fifo,
+ ASCFIFOState),
+ VMSTATE_UINT8_ARRAY(regs, ASCState, ASC_REG_SIZE),
+ VMSTATE_INT64(fifo_empty_ns, ASCState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void asc_fifo_reset(ASCFIFOState *fs)
+{
+ fs->wptr = 0;
+ fs->rptr = 0;
+ fs->cnt = 0;
+ fs->xa_cnt = -1;
+ fs->int_status = 0;
+}
+
+static void asc_fifo_init(ASCFIFOState *fs, int index)
+{
+ ASCState *s = container_of(fs, ASCState, fifos[index]);
+ char *name;
+
+ fs->index = index;
+ name = g_strdup_printf("asc.fifo%c", 'A' + index);
+ memory_region_init_io(&fs->mem_fifo, OBJECT(s), &asc_fifo_ops, fs,
+ name, ASC_FIFO_SIZE);
+ g_free(name);
+
+ name = g_strdup_printf("asc.extregs%c", 'A' + index);
+ memory_region_init_io(&fs->mem_extregs, OBJECT(s), &asc_extregs_ops,
+ fs, name, ASC_EXTREG_SIZE);
+ g_free(name);
+}
+
+static void asc_reset_hold(Object *obj)
+{
+ ASCState *s = ASC(obj);
+
+ AUD_set_active_out(s->voice, 0);
+
+ memset(s->regs, 0, sizeof(s->regs));
+ asc_fifo_reset(&s->fifos[0]);
+ asc_fifo_reset(&s->fifos[1]);
+ s->fifo_empty_ns = 0;
+
+ if (s->type == ASC_TYPE_ASC) {
+ /* FIFO half full IRQs enabled by default */
+ s->fifos[0].extregs[ASC_EXTREGS_INTCTRL] = 1;
+ s->fifos[1].extregs[ASC_EXTREGS_INTCTRL] = 1;
+ }
+}
+
+static void asc_unrealize(DeviceState *dev)
+{
+ ASCState *s = ASC(dev);
+
+ g_free(s->mixbuf);
+ g_free(s->silentbuf);
+
+ AUD_remove_card(&s->card);
+}
+
+static void asc_realize(DeviceState *dev, Error **errp)
+{
+ ASCState *s = ASC(dev);
+ struct audsettings as;
+
+ if (!AUD_register_card("Apple Sound Chip", &s->card, errp)) {
+ return;
+ }
+
+ as.freq = ASC_FREQ;
+ as.nchannels = 2;
+ as.fmt = AUDIO_FORMAT_U8;
+ as.endianness = AUDIO_HOST_ENDIANNESS;
+
+ s->voice = AUD_open_out(&s->card, s->voice, "asc.out", s, asc_out_cb,
+ &as);
+ s->shift = 1;
+ s->samples = AUD_get_buffer_size_out(s->voice) >> s->shift;
+ s->mixbuf = g_malloc0(s->samples << s->shift);
+
+ s->silentbuf = g_malloc0(s->samples << s->shift);
+ memset(s->silentbuf, 0x80, s->samples << s->shift);
+
+ /* Add easc registers if required */
+ if (s->type == ASC_TYPE_EASC) {
+ memory_region_add_subregion(&s->asc, ASC_EXTREG_OFFSET,
+ &s->fifos[0].mem_extregs);
+ memory_region_add_subregion(&s->asc,
+ ASC_EXTREG_OFFSET + ASC_EXTREG_SIZE,
+ &s->fifos[1].mem_extregs);
+ }
+}
+
+static void asc_init(Object *obj)
+{
+ ASCState *s = ASC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+ memory_region_init(&s->asc, OBJECT(obj), "asc", ASC_SIZE);
+
+ asc_fifo_init(&s->fifos[0], 0);
+ asc_fifo_init(&s->fifos[1], 1);
+
+ memory_region_add_subregion(&s->asc, ASC_FIFO_OFFSET,
+ &s->fifos[0].mem_fifo);
+ memory_region_add_subregion(&s->asc,
+ ASC_FIFO_OFFSET + ASC_FIFO_SIZE,
+ &s->fifos[1].mem_fifo);
+
+ memory_region_init_io(&s->mem_regs, OBJECT(obj), &asc_regs_ops, s,
+ "asc.regs", ASC_REG_SIZE);
+ memory_region_add_subregion(&s->asc, ASC_REG_OFFSET, &s->mem_regs);
+
+ sysbus_init_irq(sbd, &s->irq);
+ sysbus_init_mmio(sbd, &s->asc);
+}
+
+static Property asc_properties[] = {
+ DEFINE_AUDIO_PROPERTIES(ASCState, card),
+ DEFINE_PROP_UINT8("asctype", ASCState, type, ASC_TYPE_ASC),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void asc_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ ResettableClass *rc = RESETTABLE_CLASS(oc);
+
+ dc->realize = asc_realize;
+ dc->unrealize = asc_unrealize;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
+ dc->vmsd = &vmstate_asc;
+ device_class_set_props(dc, asc_properties);
+ rc->phases.hold = asc_reset_hold;
+}
+
+static const TypeInfo asc_info_types[] = {
+ {
+ .name = TYPE_ASC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(ASCState),
+ .instance_init = asc_init,
+ .class_init = asc_class_init,
+ },
+};
+
+DEFINE_TYPES(asc_info_types)
diff --git a/hw/audio/meson.build b/hw/audio/meson.build
index d0fda10..8805322 100644
--- a/hw/audio/meson.build
+++ b/hw/audio/meson.build
@@ -1,6 +1,7 @@
system_ss.add(files('soundhw.c'))
system_ss.add(when: 'CONFIG_AC97', if_true: files('ac97.c'))
system_ss.add(when: 'CONFIG_ADLIB', if_true: files('fmopl.c', 'adlib.c'))
+system_ss.add(when: 'CONFIG_ASC', if_true: files('asc.c'))
system_ss.add(when: 'CONFIG_CS4231', if_true: files('cs4231.c'))
system_ss.add(when: 'CONFIG_CS4231A', if_true: files('cs4231a.c'))
system_ss.add(when: 'CONFIG_ES1370', if_true: files('es1370.c'))
diff --git a/hw/audio/soundhw.c b/hw/audio/soundhw.c
index 94d9463..b387b0e 100644
--- a/hw/audio/soundhw.c
+++ b/hw/audio/soundhw.c
@@ -83,7 +83,7 @@ void show_valid_soundhw(void)
static struct soundhw *selected = NULL;
static const char *audiodev_id;
-void select_soundhw(const char *optarg, const char *audiodev)
+void select_soundhw(const char *name, const char *audiodev)
{
struct soundhw *c;
@@ -92,7 +92,7 @@ void select_soundhw(const char *optarg, const char *audiodev)
}
for (c = soundhw; c->name; ++c) {
- if (g_str_equal(c->name, optarg)) {
+ if (g_str_equal(c->name, name)) {
selected = c;
audiodev_id = audiodev;
break;
@@ -100,7 +100,7 @@ void select_soundhw(const char *optarg, const char *audiodev)
}
if (!c->name) {
- error_report("Unknown sound card name `%s'", optarg);
+ error_report("Unknown sound card name `%s'", name);
show_valid_soundhw();
exit(1);
}
diff --git a/hw/audio/trace-events b/hw/audio/trace-events
index 4dec48a..89ef299 100644
--- a/hw/audio/trace-events
+++ b/hw/audio/trace-events
@@ -17,3 +17,13 @@ via_ac97_codec_write(uint8_t addr, uint16_t val) "0x%x <- 0x%x"
via_ac97_sgd_fetch(uint32_t curr, uint32_t addr, char stop, char eol, char flag, uint32_t len) "curr=0x%x addr=0x%x %c%c%c len=%d"
via_ac97_sgd_read(uint64_t addr, unsigned size, uint64_t val) "0x%"PRIx64" %d -> 0x%"PRIx64
via_ac97_sgd_write(uint64_t addr, unsigned size, uint64_t val) "0x%"PRIx64" %d <- 0x%"PRIx64
+
+# asc.c
+asc_read_fifo(const char fifo, int reg, unsigned size, uint64_t value) "fifo %c reg=0x%03x size=%u value=0x%"PRIx64
+asc_read_reg(int reg, unsigned size, uint64_t value) "reg=0x%03x size=%u value=0x%"PRIx64
+asc_read_extreg(const char fifo, int reg, unsigned size, uint64_t value) "fifo %c reg=0x%03x size=%u value=0x%"PRIx64
+asc_fifo_get(const char fifo, int rptr, int cnt, uint64_t value) "fifo %c rptr=0x%x cnt=0x%x value=0x%"PRIx64
+asc_write_fifo(const char fifo, int reg, unsigned size, int wrptr, int cnt, uint64_t value) "fifo %c reg=0x%03x size=%u wptr=0x%x cnt=0x%x value=0x%"PRIx64
+asc_write_reg(int reg, unsigned size, uint64_t value) "reg=0x%03x size=%u value=0x%"PRIx64
+asc_write_extreg(const char fifo, int reg, unsigned size, uint64_t value) "fifo %c reg=0x%03x size=%u value=0x%"PRIx64
+asc_update_irq(int irq, int a, int b) "set IRQ to %d (A: 0x%x B: 0x%x)"
diff --git a/hw/block/swim.c b/hw/block/swim.c
index 333da08..fd65c59 100644
--- a/hw/block/swim.c
+++ b/hw/block/swim.c
@@ -19,25 +19,30 @@
#include "hw/block/block.h"
#include "hw/block/swim.h"
#include "hw/qdev-properties.h"
+#include "trace.h"
+
+
+/* IWM latch bits */
+
+#define IWMLB_PHASE0 0
+#define IWMLB_PHASE1 1
+#define IWMLB_PHASE2 2
+#define IWMLB_PHASE3 3
+#define IWMLB_MOTORON 4
+#define IWMLB_DRIVESEL 5
+#define IWMLB_L6 6
+#define IWMLB_L7 7
/* IWM registers */
-#define IWM_PH0L 0
-#define IWM_PH0H 1
-#define IWM_PH1L 2
-#define IWM_PH1H 3
-#define IWM_PH2L 4
-#define IWM_PH2H 5
-#define IWM_PH3L 6
-#define IWM_PH3H 7
-#define IWM_MTROFF 8
-#define IWM_MTRON 9
-#define IWM_INTDRIVE 10
-#define IWM_EXTDRIVE 11
-#define IWM_Q6L 12
-#define IWM_Q6H 13
-#define IWM_Q7L 14
-#define IWM_Q7H 15
+#define IWM_READALLONES 0
+#define IWM_READDATA 1
+#define IWM_READSTATUS0 2
+#define IWM_READSTATUS1 3
+#define IWM_READWHANDSHAKE0 4
+#define IWM_READWHANDSHAKE1 5
+#define IWM_WRITESETMODE 6
+#define IWM_WRITEDATA 7
/* SWIM registers */
@@ -61,8 +66,9 @@
#define REG_SHIFT 9
-#define SWIM_MODE_IWM 0
-#define SWIM_MODE_SWIM 1
+#define SWIM_MODE_STATUS_BIT 6
+#define SWIM_MODE_IWM 0
+#define SWIM_MODE_ISM 1
/* bits in phase register */
@@ -125,6 +131,18 @@
#define SWIM_HEDSEL 0x20
#define SWIM_MOTON 0x80
+static const char *iwm_reg_names[] = {
+ "READALLONES", "READDATA", "READSTATUS0", "READSTATUS1",
+ "READWHANDSHAKE0", "READWHANDSHAKE1", "WRITESETMODE", "WRITEDATA"
+};
+
+static const char *ism_reg_names[] = {
+ "WRITE_DATA", "WRITE_MARK", "WRITE_CRC", "WRITE_PARAMETER",
+ "WRITE_PHASE", "WRITE_SETUP", "WRITE_MODE0", "WRITE_MODE1",
+ "READ_DATA", "READ_MARK", "READ_ERROR", "READ_PARAMETER",
+ "READ_PHASE", "READ_SETUP", "READ_STATUS", "READ_HANDSHAKE"
+};
+
static void fd_recalibrate(FDrive *drive)
{
}
@@ -259,102 +277,158 @@ static const TypeInfo swim_bus_info = {
.instance_size = sizeof(SWIMBus),
};
-static void iwmctrl_write(void *opaque, hwaddr reg, uint64_t value,
+static void iwmctrl_write(void *opaque, hwaddr addr, uint64_t value,
unsigned size)
{
SWIMCtrl *swimctrl = opaque;
+ uint8_t latch, reg, ism_bit;
- reg >>= REG_SHIFT;
+ addr >>= REG_SHIFT;
- swimctrl->regs[reg >> 1] = reg & 1;
-
- if (swimctrl->regs[IWM_Q6] &&
- swimctrl->regs[IWM_Q7]) {
- if (swimctrl->regs[IWM_MTR]) {
- /* data register */
- swimctrl->iwm_data = value;
- } else {
- /* mode register */
- swimctrl->iwm_mode = value;
- /* detect sequence to switch from IWM mode to SWIM mode */
- switch (swimctrl->iwm_switch) {
- case 0:
- if (value == 0x57) {
- swimctrl->iwm_switch++;
- }
- break;
- case 1:
- if (value == 0x17) {
- swimctrl->iwm_switch++;
- }
- break;
- case 2:
- if (value == 0x57) {
- swimctrl->iwm_switch++;
- }
- break;
- case 3:
- if (value == 0x57) {
- swimctrl->mode = SWIM_MODE_SWIM;
- swimctrl->iwm_switch = 0;
- }
- break;
+ /* A3-A1 select a latch, A0 specifies the value */
+ latch = (addr >> 1) & 7;
+ if (addr & 1) {
+ swimctrl->iwm_latches |= (1 << latch);
+ } else {
+ swimctrl->iwm_latches &= ~(1 << latch);
+ }
+
+ reg = (swimctrl->iwm_latches & 0xc0) >> 5 |
+ (swimctrl->iwm_latches & 0x10) >> 4;
+
+ swimctrl->iwmregs[reg] = value;
+ trace_swim_iwmctrl_write(reg, iwm_reg_names[reg], size, value);
+
+ switch (reg) {
+ case IWM_WRITESETMODE:
+ /* detect sequence to switch from IWM mode to SWIM mode */
+ ism_bit = (value & (1 << SWIM_MODE_STATUS_BIT));
+
+ switch (swimctrl->iwm_switch) {
+ case 0:
+ if (ism_bit) { /* 1 */
+ swimctrl->iwm_switch++;
+ }
+ break;
+ case 1:
+ if (!ism_bit) { /* 0 */
+ swimctrl->iwm_switch++;
+ }
+ break;
+ case 2:
+ if (ism_bit) { /* 1 */
+ swimctrl->iwm_switch++;
+ }
+ break;
+ case 3:
+ if (ism_bit) { /* 1 */
+ swimctrl->iwm_switch++;
+
+ swimctrl->mode = SWIM_MODE_ISM;
+ swimctrl->swim_mode |= (1 << SWIM_MODE_STATUS_BIT);
+ swimctrl->iwm_switch = 0;
+ trace_swim_switch_to_ism();
+
+ /* Switch to ISM registers */
+ memory_region_del_subregion(&swimctrl->swim, &swimctrl->iwm);
+ memory_region_add_subregion(&swimctrl->swim, 0x0,
+ &swimctrl->ism);
}
+ break;
}
+ break;
+ default:
+ break;
}
}
-static uint64_t iwmctrl_read(void *opaque, hwaddr reg, unsigned size)
+static uint64_t iwmctrl_read(void *opaque, hwaddr addr, unsigned size)
{
SWIMCtrl *swimctrl = opaque;
+ uint8_t latch, reg, value;
- reg >>= REG_SHIFT;
+ addr >>= REG_SHIFT;
+
+ /* A3-A1 select a latch, A0 specifies the value */
+ latch = (addr >> 1) & 7;
+ if (addr & 1) {
+ swimctrl->iwm_latches |= (1 << latch);
+ } else {
+ swimctrl->iwm_latches &= ~(1 << latch);
+ }
+
+ reg = (swimctrl->iwm_latches & 0xc0) >> 5 |
+ (swimctrl->iwm_latches & 0x10) >> 4;
- swimctrl->regs[reg >> 1] = reg & 1;
+ switch (reg) {
+ case IWM_READALLONES:
+ value = 0xff;
+ break;
+ default:
+ value = 0;
+ break;
+ }
- return 0;
+ trace_swim_iwmctrl_read(reg, iwm_reg_names[reg], size, value);
+ return value;
}
-static void swimctrl_write(void *opaque, hwaddr reg, uint64_t value,
- unsigned size)
+static const MemoryRegionOps swimctrl_iwm_ops = {
+ .write = iwmctrl_write,
+ .read = iwmctrl_read,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void ismctrl_write(void *opaque, hwaddr reg, uint64_t value,
+ unsigned size)
{
SWIMCtrl *swimctrl = opaque;
- if (swimctrl->mode == SWIM_MODE_IWM) {
- iwmctrl_write(opaque, reg, value, size);
- return;
- }
-
reg >>= REG_SHIFT;
+ trace_swim_ismctrl_write(reg, ism_reg_names[reg], size, value);
+
switch (reg) {
case SWIM_WRITE_PHASE:
swimctrl->swim_phase = value;
break;
case SWIM_WRITE_MODE0:
swimctrl->swim_mode &= ~value;
+ /* Any access to MODE0 register resets PRAM index */
+ swimctrl->pram_idx = 0;
+
+ if (!(swimctrl->swim_mode & (1 << SWIM_MODE_STATUS_BIT))) {
+ /* Clearing the mode bit switches to IWM mode */
+ swimctrl->mode = SWIM_MODE_IWM;
+ swimctrl->iwm_latches = 0;
+ trace_swim_switch_to_iwm();
+
+ /* Switch to IWM registers */
+ memory_region_del_subregion(&swimctrl->swim, &swimctrl->ism);
+ memory_region_add_subregion(&swimctrl->swim, 0x0,
+ &swimctrl->iwm);
+ }
break;
case SWIM_WRITE_MODE1:
swimctrl->swim_mode |= value;
break;
+ case SWIM_WRITE_PARAMETER:
+ swimctrl->pram[swimctrl->pram_idx++] = value;
+ swimctrl->pram_idx &= 0xf;
+ break;
case SWIM_WRITE_DATA:
case SWIM_WRITE_MARK:
case SWIM_WRITE_CRC:
- case SWIM_WRITE_PARAMETER:
case SWIM_WRITE_SETUP:
break;
}
}
-static uint64_t swimctrl_read(void *opaque, hwaddr reg, unsigned size)
+static uint64_t ismctrl_read(void *opaque, hwaddr reg, unsigned size)
{
SWIMCtrl *swimctrl = opaque;
uint32_t value = 0;
- if (swimctrl->mode == SWIM_MODE_IWM) {
- return iwmctrl_read(opaque, reg, size);
- }
-
reg >>= REG_SHIFT;
switch (reg) {
@@ -367,22 +441,31 @@ static uint64_t swimctrl_read(void *opaque, hwaddr reg, unsigned size)
value = SWIM_SENSE;
}
break;
+ case SWIM_READ_PARAMETER:
+ value = swimctrl->pram[swimctrl->pram_idx++];
+ swimctrl->pram_idx &= 0xf;
+ break;
+ case SWIM_READ_STATUS:
+ value = swimctrl->swim_status & ~(1 << SWIM_MODE_STATUS_BIT);
+ if (swimctrl->swim_mode == SWIM_MODE_ISM) {
+ value |= (1 << SWIM_MODE_STATUS_BIT);
+ }
+ break;
case SWIM_READ_DATA:
case SWIM_READ_MARK:
case SWIM_READ_ERROR:
- case SWIM_READ_PARAMETER:
case SWIM_READ_SETUP:
- case SWIM_READ_STATUS:
break;
}
+ trace_swim_ismctrl_read(reg, ism_reg_names[reg], size, value);
return value;
}
-static const MemoryRegionOps swimctrl_mem_ops = {
- .write = swimctrl_write,
- .read = swimctrl_read,
- .endianness = DEVICE_NATIVE_ENDIAN,
+static const MemoryRegionOps swimctrl_ism_ops = {
+ .write = ismctrl_write,
+ .read = ismctrl_read,
+ .endianness = DEVICE_BIG_ENDIAN,
};
static void sysbus_swim_reset(DeviceState *d)
@@ -393,13 +476,11 @@ static void sysbus_swim_reset(DeviceState *d)
ctrl->mode = 0;
ctrl->iwm_switch = 0;
- for (i = 0; i < 8; i++) {
- ctrl->regs[i] = 0;
- }
- ctrl->iwm_data = 0;
- ctrl->iwm_mode = 0;
+ memset(ctrl->iwmregs, 0, sizeof(ctrl->iwmregs));
+
ctrl->swim_phase = 0;
ctrl->swim_mode = 0;
+ memset(ctrl->ismregs, 0, sizeof(ctrl->ismregs));
for (i = 0; i < SWIM_MAX_FD; i++) {
fd_recalibrate(&ctrl->drives[i]);
}
@@ -411,9 +492,12 @@ static void sysbus_swim_init(Object *obj)
Swim *sbs = SWIM(obj);
SWIMCtrl *swimctrl = &sbs->ctrl;
- memory_region_init_io(&swimctrl->iomem, obj, &swimctrl_mem_ops, swimctrl,
- "swim", 0x2000);
- sysbus_init_mmio(sbd, &swimctrl->iomem);
+ memory_region_init(&swimctrl->swim, obj, "swim", 0x2000);
+ memory_region_init_io(&swimctrl->iwm, obj, &swimctrl_iwm_ops, swimctrl,
+ "iwm", 0x2000);
+ memory_region_init_io(&swimctrl->ism, obj, &swimctrl_ism_ops, swimctrl,
+ "ism", 0x2000);
+ sysbus_init_mmio(sbd, &swimctrl->swim);
}
static void sysbus_swim_realize(DeviceState *dev, Error **errp)
@@ -423,6 +507,9 @@ static void sysbus_swim_realize(DeviceState *dev, Error **errp)
qbus_init(&swimctrl->bus, sizeof(SWIMBus), TYPE_SWIM_BUS, dev, NULL);
swimctrl->bus.ctrl = swimctrl;
+
+ /* Default register set is IWM */
+ memory_region_add_subregion(&swimctrl->swim, 0x0, &swimctrl->iwm);
}
static const VMStateDescription vmstate_fdrive = {
@@ -442,10 +529,10 @@ static const VMStateDescription vmstate_swim = {
VMSTATE_INT32(mode, SWIMCtrl),
/* IWM mode */
VMSTATE_INT32(iwm_switch, SWIMCtrl),
- VMSTATE_UINT16_ARRAY(regs, SWIMCtrl, 8),
- VMSTATE_UINT8(iwm_data, SWIMCtrl),
- VMSTATE_UINT8(iwm_mode, SWIMCtrl),
+ VMSTATE_UINT8(iwm_latches, SWIMCtrl),
+ VMSTATE_UINT8_ARRAY(iwmregs, SWIMCtrl, 8),
/* SWIM mode */
+ VMSTATE_UINT8_ARRAY(ismregs, SWIMCtrl, 16),
VMSTATE_UINT8(swim_phase, SWIMCtrl),
VMSTATE_UINT8(swim_mode, SWIMCtrl),
/* Drives */
diff --git a/hw/block/trace-events b/hw/block/trace-events
index 34be8b9..bab21d3 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -90,3 +90,11 @@ m25p80_read_data(void *s, uint32_t pos, uint8_t v) "[%p] Read data 0x%"PRIx32"=0
m25p80_read_sfdp(void *s, uint32_t addr, uint8_t v) "[%p] Read SFDP 0x%"PRIx32"=0x%"PRIx8
m25p80_binding(void *s) "[%p] Binding to IF_MTD drive"
m25p80_binding_no_bdrv(void *s) "[%p] No BDRV - binding to RAM"
+
+# swim.c
+swim_ismctrl_read(int reg, const char *name, unsigned size, uint64_t value) "reg=%d [%s] size=%u value=0x%"PRIx64
+swim_ismctrl_write(int reg, const char *name, unsigned size, uint64_t value) "reg=%d [%s] size=%u value=0x%"PRIx64
+swim_iwmctrl_read(int reg, const char *name, unsigned size, uint64_t value) "reg=%d [%s] size=%u value=0x%"PRIx64
+swim_iwmctrl_write(int reg, const char *name, unsigned size, uint64_t value) "reg=%d [%s] size=%u value=0x%"PRIx64
+swim_switch_to_ism(void) "switch from IWM to ISM mode"
+swim_switch_to_iwm(void) "switch from ISM to IWM mode"
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
index 4d40699..bab8942 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -228,8 +228,8 @@ static void cpu_common_initfn(Object *obj)
cpu->cpu_index = UNASSIGNED_CPU_INDEX;
cpu->cluster_index = UNASSIGNED_CLUSTER_INDEX;
cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
- /* *-user doesn't have configurable SMP topology */
- /* the default value is changed by qemu_init_vcpu() for softmmu */
+ /* user-mode doesn't have configurable SMP topology */
+ /* the default value is changed by qemu_init_vcpu() for system-mode */
cpu->nr_cores = 1;
cpu->nr_threads = 1;
cpu->cflags_next_tb = -1;
diff --git a/hw/cxl/cxl-device-utils.c b/hw/cxl/cxl-device-utils.c
index 517f06d..bd683280 100644
--- a/hw/cxl/cxl-device-utils.c
+++ b/hw/cxl/cxl-device-utils.c
@@ -283,13 +283,13 @@ static void memdev_reg_init_common(CXLDeviceState *cxl_dstate) { }
void cxl_device_register_init_common(CXLDeviceState *cxl_dstate)
{
- uint64_t *cap_hdrs = cxl_dstate->caps_reg_state64;
+ uint64_t *cap_h = cxl_dstate->caps_reg_state64;
const int cap_count = 3;
/* CXL Device Capabilities Array Register */
- ARRAY_FIELD_DP64(cap_hdrs, CXL_DEV_CAP_ARRAY, CAP_ID, 0);
- ARRAY_FIELD_DP64(cap_hdrs, CXL_DEV_CAP_ARRAY, CAP_VERSION, 1);
- ARRAY_FIELD_DP64(cap_hdrs, CXL_DEV_CAP_ARRAY, CAP_COUNT, cap_count);
+ ARRAY_FIELD_DP64(cap_h, CXL_DEV_CAP_ARRAY, CAP_ID, 0);
+ ARRAY_FIELD_DP64(cap_h, CXL_DEV_CAP_ARRAY, CAP_VERSION, 1);
+ ARRAY_FIELD_DP64(cap_h, CXL_DEV_CAP_ARRAY, CAP_COUNT, cap_count);
cxl_device_cap_init(cxl_dstate, DEVICE_STATUS, 1, 2);
device_reg_init_common(cxl_dstate);
diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c
index fec22d8..2909a73 100644
--- a/hw/i386/acpi-microvm.c
+++ b/hw/i386/acpi-microvm.c
@@ -55,8 +55,8 @@ static void acpi_dsdt_add_virtio(Aml *scope,
bus = sysbus_get_default();
QTAILQ_FOREACH(kid, &bus->children, sibling) {
- DeviceState *dev = kid->child;
- Object *obj = object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MMIO);
+ Object *obj = object_dynamic_cast(OBJECT(kid->child),
+ TYPE_VIRTIO_MMIO);
if (obj) {
VirtIOMMIOProxy *mmio = VIRTIO_MMIO(obj);
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index aad7e8c..bb3854d 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1049,7 +1049,6 @@ void pc_memory_init(PCMachineState *pcms,
if (machine->device_memory) {
uint64_t *val = g_malloc(sizeof(*val));
- PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
uint64_t res_mem_end = machine->device_memory->base;
if (!pcmc->broken_reserved_end) {
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index f034df8..b3d0548 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -365,8 +365,6 @@ void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
cpu_slot = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, &idx);
if (!cpu_slot) {
- MachineState *ms = MACHINE(x86ms);
-
x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids);
error_setg(errp,
"Invalid CPU [socket: %u, die: %u, core: %u, thread: %u] with"
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index d0a774b..fcc5476 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1622,9 +1622,7 @@ void ahci_uninit(AHCIState *s)
AHCIDevice *ad = &s->dev[i];
for (j = 0; j < 2; j++) {
- IDEState *s = &ad->port.ifs[j];
-
- ide_exit(s);
+ ide_exit(&ad->port.ifs[j]);
}
object_unparent(OBJECT(&ad->port));
}
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 2629128..b0a004f 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -662,7 +662,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
sysbus_mmio_get_region(d, 2));
/* Connect pch_pic irqs to extioi */
- for (int i = 0; i < num; i++) {
+ for (i = 0; i < num; i++) {
qdev_connect_gpio_out(DEVICE(d), i, qdev_get_gpio_in(extioi, i));
}
diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig
index f839f8a..d88741e 100644
--- a/hw/m68k/Kconfig
+++ b/hw/m68k/Kconfig
@@ -23,6 +23,9 @@ config Q800
select ESP
select DP8393X
select OR_IRQ
+ select DJMEMC
+ select IOSB
+ select ASC
config M68K_VIRT
bool
diff --git a/hw/m68k/q800-glue.c b/hw/m68k/q800-glue.c
index 34c4f0e..f413b15 100644
--- a/hw/m68k/q800-glue.c
+++ b/hw/m68k/q800-glue.c
@@ -97,6 +97,11 @@ static void GLUE_set_irq(void *opaque, int irq, int level)
irq = 6;
break;
+ case GLUE_IRQ_IN_ASC:
+ /* Route to VIA2 instead, negative edge-triggered */
+ qemu_set_irq(s->irqs[GLUE_IRQ_ASC], !level);
+ return;
+
default:
g_assert_not_reached();
}
@@ -123,6 +128,10 @@ static void GLUE_set_irq(void *opaque, int irq, int level)
irq = 6;
break;
+ case GLUE_IRQ_IN_ASC:
+ irq = 4;
+ break;
+
default:
g_assert_not_reached();
}
@@ -166,9 +175,9 @@ static void glue_nmi_release(void *opaque)
GLUE_set_irq(s, GLUE_IRQ_IN_NMI, 0);
}
-static void glue_reset(DeviceState *dev)
+static void glue_reset_hold(Object *obj)
{
- GLUEState *s = GLUE(dev);
+ GLUEState *s = GLUE(obj);
s->ipr = 0;
s->auxmode = 0;
@@ -214,7 +223,7 @@ static void glue_init(Object *obj)
qdev_init_gpio_in(dev, GLUE_set_irq, 8);
qdev_init_gpio_in_named(dev, glue_auxmode_set_irq, "auxmode", 1);
- qdev_init_gpio_out(dev, s->irqs, 1);
+ qdev_init_gpio_out(dev, s->irqs, 2);
/* NMI release timer */
s->nmi_release = timer_new_ms(QEMU_CLOCK_VIRTUAL, glue_nmi_release, s);
@@ -223,11 +232,12 @@ static void glue_init(Object *obj)
static void glue_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
NMIClass *nc = NMI_CLASS(klass);
dc->vmsd = &vmstate_glue;
- dc->reset = glue_reset;
device_class_set_props(dc, glue_properties);
+ rc->phases.hold = glue_reset_hold;
nc->nmi_monitor_handler = glue_nmi;
}
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index b770b71..1d7cd5f 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -40,7 +40,10 @@
#include "hw/m68k/q800.h"
#include "hw/m68k/q800-glue.h"
#include "hw/misc/mac_via.h"
+#include "hw/misc/djmemc.h"
+#include "hw/misc/iosb.h"
#include "hw/input/adb.h"
+#include "hw/audio/asc.h"
#include "hw/nubus/mac-nubus-bridge.h"
#include "hw/display/macfb.h"
#include "hw/block/swim.h"
@@ -66,9 +69,11 @@
#define SONIC_PROM_BASE (IO_BASE + 0x08000)
#define SONIC_BASE (IO_BASE + 0x0a000)
#define SCC_BASE (IO_BASE + 0x0c020)
+#define DJMEMC_BASE (IO_BASE + 0x0e000)
#define ESP_BASE (IO_BASE + 0x10000)
#define ESP_PDMA (IO_BASE + 0x10100)
#define ASC_BASE (IO_BASE + 0x14000)
+#define IOSB_BASE (IO_BASE + 0x18000)
#define SWIM_BASE (IO_BASE + 0x1E000)
#define SONIC_PROM_SIZE 0x1000
@@ -82,6 +87,9 @@
#define MAC_CLOCK 3686418
+/* Size of whole RAM area */
+#define RAM_SIZE 0x40000000
+
/*
* Slot 0x9 is reserved for use by the in-built framebuffer whilst only
* slots 0xc, 0xd and 0xe physically exist on the Quadra 800
@@ -89,6 +97,9 @@
#define Q800_NUBUS_SLOTS_AVAILABLE (BIT(0x9) | BIT(0xc) | BIT(0xd) | \
BIT(0xe))
+/* Quadra 800 machine ID */
+#define Q800_MACHINE_ID 0xa55a2bad
+
static void main_cpu_reset(void *opaque)
{
@@ -190,6 +201,48 @@ static const MemoryRegionOps macio_alias_ops = {
},
};
+static uint64_t machine_id_read(void *opaque, hwaddr addr, unsigned size)
+{
+ return Q800_MACHINE_ID;
+}
+
+static void machine_id_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ return;
+}
+
+static const MemoryRegionOps machine_id_ops = {
+ .read = machine_id_read,
+ .write = machine_id_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+static uint64_t ramio_read(void *opaque, hwaddr addr, unsigned size)
+{
+ return 0x0;
+}
+
+static void ramio_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ return;
+}
+
+static const MemoryRegionOps ramio_ops = {
+ .read = ramio_read,
+ .write = ramio_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 4,
+ },
+};
+
static void q800_machine_init(MachineState *machine)
{
Q800MachineState *m = Q800_MACHINE(machine);
@@ -234,7 +287,11 @@ static void q800_machine_init(MachineState *machine)
qemu_register_reset(main_cpu_reset, &m->cpu);
/* RAM */
- memory_region_add_subregion(get_system_memory(), 0, machine->ram);
+ memory_region_init_io(&m->ramio, OBJECT(machine), &ramio_ops, &m->ramio,
+ "ram", RAM_SIZE);
+ memory_region_add_subregion(get_system_memory(), 0x0, &m->ramio);
+
+ memory_region_add_subregion(&m->ramio, 0, machine->ram);
/*
* Create container for all IO devices
@@ -251,12 +308,32 @@ static void q800_machine_init(MachineState *machine)
memory_region_add_subregion(get_system_memory(), IO_BASE + IO_SLICE,
&m->macio_alias);
+ memory_region_init_io(&m->machine_id, NULL, &machine_id_ops, NULL,
+ "Machine ID", 4);
+ memory_region_add_subregion(get_system_memory(), 0x5ffffffc,
+ &m->machine_id);
+
/* IRQ Glue */
object_initialize_child(OBJECT(machine), "glue", &m->glue, TYPE_GLUE);
object_property_set_link(OBJECT(&m->glue), "cpu", OBJECT(&m->cpu),
&error_abort);
sysbus_realize(SYS_BUS_DEVICE(&m->glue), &error_fatal);
+ /* djMEMC memory controller */
+ object_initialize_child(OBJECT(machine), "djmemc", &m->djmemc,
+ TYPE_DJMEMC);
+ sysbus = SYS_BUS_DEVICE(&m->djmemc);
+ sysbus_realize_and_unref(sysbus, &error_fatal);
+ memory_region_add_subregion(&m->macio, DJMEMC_BASE - IO_BASE,
+ sysbus_mmio_get_region(sysbus, 0));
+
+ /* IOSB subsystem */
+ object_initialize_child(OBJECT(machine), "iosb", &m->iosb, TYPE_IOSB);
+ sysbus = SYS_BUS_DEVICE(&m->iosb);
+ sysbus_realize_and_unref(sysbus, &error_fatal);
+ memory_region_add_subregion(&m->macio, IOSB_BASE - IO_BASE,
+ sysbus_mmio_get_region(sysbus, 0));
+
/* VIA 1 */
object_initialize_child(OBJECT(machine), "via1", &m->via1,
TYPE_MOS6522_Q800_VIA1);
@@ -374,6 +451,12 @@ static void q800_machine_init(MachineState *machine)
memory_region_add_subregion(&m->macio, SCC_BASE - IO_BASE,
sysbus_mmio_get_region(sysbus, 0));
+ /* Create alias for NetBSD */
+ memory_region_init_alias(&m->escc_alias, OBJECT(machine), "escc-alias",
+ sysbus_mmio_get_region(sysbus, 0), 0, 0x8);
+ memory_region_add_subregion(&m->macio, SCC_BASE - IO_BASE - 0x20,
+ &m->escc_alias);
+
/* SCSI */
object_initialize_child(OBJECT(machine), "esp", &m->esp,
@@ -404,6 +487,26 @@ static void q800_machine_init(MachineState *machine)
scsi_bus_legacy_handle_cmdline(&esp->bus);
+ /* Apple Sound Chip */
+
+ object_initialize_child(OBJECT(machine), "asc", &m->asc, TYPE_ASC);
+ qdev_prop_set_uint8(DEVICE(&m->asc), "asctype", m->easc ? ASC_TYPE_EASC
+ : ASC_TYPE_ASC);
+ if (machine->audiodev) {
+ qdev_prop_set_string(DEVICE(&m->asc), "audiodev", machine->audiodev);
+ }
+ sysbus = SYS_BUS_DEVICE(&m->asc);
+ sysbus_realize_and_unref(sysbus, &error_fatal);
+ memory_region_add_subregion(&m->macio, ASC_BASE - IO_BASE,
+ sysbus_mmio_get_region(sysbus, 0));
+ sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(DEVICE(&m->glue),
+ GLUE_IRQ_IN_ASC));
+
+ /* Wire ASC IRQ via GLUE for use in classic mode */
+ qdev_connect_gpio_out(DEVICE(&m->glue), GLUE_IRQ_ASC,
+ qdev_get_gpio_in(DEVICE(&m->via2),
+ VIA2_IRQ_ASC_BIT));
+
/* SWIM floppy controller */
object_initialize_child(OBJECT(machine), "swim", &m->swim,
@@ -557,6 +660,11 @@ static void q800_machine_init(MachineState *machine)
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
memory_region_add_subregion(get_system_memory(), MACROM_ADDR, &m->rom);
+ memory_region_init_alias(&m->rom_alias, NULL, "m68k_mac.rom-alias",
+ &m->rom, 0, MACROM_SIZE);
+ memory_region_add_subregion(get_system_memory(), 0x40000000,
+ &m->rom_alias);
+
/* Load MacROM binary */
if (filename) {
bios_size = load_image_targphys(filename, MACROM_ADDR, MACROM_SIZE);
@@ -581,6 +689,28 @@ static void q800_machine_init(MachineState *machine)
}
}
+static bool q800_get_easc(Object *obj, Error **errp)
+{
+ Q800MachineState *ms = Q800_MACHINE(obj);
+
+ return ms->easc;
+}
+
+static void q800_set_easc(Object *obj, bool value, Error **errp)
+{
+ Q800MachineState *ms = Q800_MACHINE(obj);
+
+ ms->easc = value;
+}
+
+static void q800_init(Object *obj)
+{
+ Q800MachineState *ms = Q800_MACHINE(obj);
+
+ /* Default to EASC */
+ ms->easc = true;
+}
+
static GlobalProperty hw_compat_q800[] = {
{ "scsi-hd", "quirk_mode_page_vendor_specific_apple", "on" },
{ "scsi-hd", "vendor", " SEAGATE" },
@@ -612,12 +742,18 @@ static void q800_machine_class_init(ObjectClass *oc, void *data)
mc->max_cpus = 1;
mc->block_default_type = IF_SCSI;
mc->default_ram_id = "m68k_mac.ram";
+ machine_add_audiodev_property(mc);
compat_props_add(mc->compat_props, hw_compat_q800, hw_compat_q800_len);
+
+ object_class_property_add_bool(oc, "easc", q800_get_easc, q800_set_easc);
+ object_class_property_set_description(oc, "easc",
+ "Set to off to use ASC rather than EASC");
}
static const TypeInfo q800_machine_typeinfo = {
.name = MACHINE_TYPE_NAME("q800"),
.parent = TYPE_MACHINE,
+ .instance_init = q800_init,
.instance_size = sizeof(Q800MachineState),
.class_init = q800_machine_class_init,
};
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 6996d26..858277b 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -186,4 +186,10 @@ config AXP2XX_PMU
bool
depends on I2C
+config DJMEMC
+ bool
+
+config IOSB
+ bool
+
source macio/Kconfig
diff --git a/hw/misc/djmemc.c b/hw/misc/djmemc.c
new file mode 100644
index 0000000..fd02640
--- /dev/null
+++ b/hw/misc/djmemc.c
@@ -0,0 +1,135 @@
+/*
+ * djMEMC, macintosh memory and interrupt controller
+ * (Quadra 610/650/800 & Centris 610/650)
+ *
+ * https://mac68k.info/wiki/display/mac68k/djMEMC+Information
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "migration/vmstate.h"
+#include "hw/misc/djmemc.h"
+#include "hw/qdev-properties.h"
+#include "trace.h"
+
+
+#define DJMEMC_INTERLEAVECONF 0x0
+#define DJMEMC_BANK0CONF 0x4
+#define DJMEMC_BANK1CONF 0x8
+#define DJMEMC_BANK2CONF 0xc
+#define DJMEMC_BANK3CONF 0x10
+#define DJMEMC_BANK4CONF 0x14
+#define DJMEMC_BANK5CONF 0x18
+#define DJMEMC_BANK6CONF 0x1c
+#define DJMEMC_BANK7CONF 0x20
+#define DJMEMC_BANK8CONF 0x24
+#define DJMEMC_BANK9CONF 0x28
+#define DJMEMC_MEMTOP 0x2c
+#define DJMEMC_CONFIG 0x30
+#define DJMEMC_REFRESH 0x34
+
+
+static uint64_t djmemc_read(void *opaque, hwaddr addr, unsigned size)
+{
+ DJMEMCState *s = opaque;
+ uint64_t val = 0;
+
+ switch (addr) {
+ case DJMEMC_INTERLEAVECONF:
+ case DJMEMC_BANK0CONF ... DJMEMC_BANK9CONF:
+ case DJMEMC_MEMTOP:
+ case DJMEMC_CONFIG:
+ case DJMEMC_REFRESH:
+ val = s->regs[addr >> 2];
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "djMEMC: unimplemented read addr=0x%"PRIx64
+ " val=0x%"PRIx64 " size=%d\n",
+ addr, val, size);
+ }
+
+ trace_djmemc_read(addr, val, size);
+ return val;
+}
+
+static void djmemc_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ DJMEMCState *s = opaque;
+
+ trace_djmemc_write(addr, val, size);
+
+ switch (addr) {
+ case DJMEMC_INTERLEAVECONF:
+ case DJMEMC_BANK0CONF ... DJMEMC_BANK9CONF:
+ case DJMEMC_MEMTOP:
+ case DJMEMC_CONFIG:
+ case DJMEMC_REFRESH:
+ s->regs[addr >> 2] = val;
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "djMEMC: unimplemented write addr=0x%"PRIx64
+ " val=0x%"PRIx64 " size=%d\n",
+ addr, val, size);
+ }
+}
+
+static const MemoryRegionOps djmemc_mmio_ops = {
+ .read = djmemc_read,
+ .write = djmemc_write,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void djmemc_init(Object *obj)
+{
+ DJMEMCState *s = DJMEMC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+ memory_region_init_io(&s->mem_regs, obj, &djmemc_mmio_ops, s, "djMEMC",
+ DJMEMC_SIZE);
+ sysbus_init_mmio(sbd, &s->mem_regs);
+}
+
+static void djmemc_reset_hold(Object *obj)
+{
+ DJMEMCState *s = DJMEMC(obj);
+
+ memset(s->regs, 0, sizeof(s->regs));
+}
+
+static const VMStateDescription vmstate_djmemc = {
+ .name = "djMEMC",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, DJMEMCState, DJMEMC_NUM_REGS),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void djmemc_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ ResettableClass *rc = RESETTABLE_CLASS(oc);
+
+ dc->vmsd = &vmstate_djmemc;
+ rc->phases.hold = djmemc_reset_hold;
+}
+
+static const TypeInfo djmemc_info_types[] = {
+ {
+ .name = TYPE_DJMEMC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(DJMEMCState),
+ .instance_init = djmemc_init,
+ .class_init = djmemc_class_init,
+ },
+};
+
+DEFINE_TYPES(djmemc_info_types)
diff --git a/hw/misc/iosb.c b/hw/misc/iosb.c
new file mode 100644
index 0000000..e7e9dcc
--- /dev/null
+++ b/hw/misc/iosb.c
@@ -0,0 +1,133 @@
+/*
+ * QEMU IOSB emulation
+ *
+ * Copyright (c) 2019 Laurent Vivier
+ * Copyright (c) 2022 Mark Cave-Ayland
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "migration/vmstate.h"
+#include "hw/sysbus.h"
+#include "hw/misc/iosb.h"
+#include "trace.h"
+
+#define IOSB_SIZE 0x2000
+
+#define IOSB_CONFIG 0x0
+#define IOSB_CONFIG2 0x100
+#define IOSB_SONIC_SCSI 0x200
+#define IOSB_REVISION 0x300
+#define IOSB_SCSI_RESID 0x400
+#define IOSB_BRIGHTNESS 0x500
+#define IOSB_TIMEOUT 0x600
+
+
+static uint64_t iosb_read(void *opaque, hwaddr addr,
+ unsigned size)
+{
+ IOSBState *s = IOSB(opaque);
+ uint64_t val = 0;
+
+ switch (addr) {
+ case IOSB_CONFIG:
+ case IOSB_CONFIG2:
+ case IOSB_SONIC_SCSI:
+ case IOSB_REVISION:
+ case IOSB_SCSI_RESID:
+ case IOSB_BRIGHTNESS:
+ case IOSB_TIMEOUT:
+ val = s->regs[addr >> 8];
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "IOSB: unimplemented read addr=0x%"PRIx64
+ " val=0x%"PRIx64 " size=%d\n",
+ addr, val, size);
+ }
+
+ trace_iosb_read(addr, val, size);
+ return val;
+}
+
+static void iosb_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ IOSBState *s = IOSB(opaque);
+
+ switch (addr) {
+ case IOSB_CONFIG:
+ case IOSB_CONFIG2:
+ case IOSB_SONIC_SCSI:
+ case IOSB_REVISION:
+ case IOSB_SCSI_RESID:
+ case IOSB_BRIGHTNESS:
+ case IOSB_TIMEOUT:
+ s->regs[addr >> 8] = val;
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "IOSB: unimplemented write addr=0x%"PRIx64
+ " val=0x%"PRIx64 " size=%d\n",
+ addr, val, size);
+ }
+
+ trace_iosb_write(addr, val, size);
+}
+
+static const MemoryRegionOps iosb_mmio_ops = {
+ .read = iosb_read,
+ .write = iosb_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void iosb_reset_hold(Object *obj)
+{
+ IOSBState *s = IOSB(obj);
+
+ memset(s->regs, 0, sizeof(s->regs));
+
+ /* BCLK 33 MHz */
+ s->regs[IOSB_CONFIG >> 8] = 1;
+}
+
+static void iosb_init(Object *obj)
+{
+ IOSBState *s = IOSB(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+ memory_region_init_io(&s->mem_regs, obj, &iosb_mmio_ops, s, "IOSB",
+ IOSB_SIZE);
+ sysbus_init_mmio(sbd, &s->mem_regs);
+}
+
+static const VMStateDescription vmstate_iosb = {
+ .name = "IOSB",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, IOSBState, IOSB_REGS),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void iosb_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ ResettableClass *rc = RESETTABLE_CLASS(oc);
+
+ dc->vmsd = &vmstate_iosb;
+ rc->phases.hold = iosb_reset_hold;
+}
+
+static const TypeInfo iosb_info_types[] = {
+ {
+ .name = TYPE_IOSB,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IOSBState),
+ .instance_init = iosb_init,
+ .class_init = iosb_class_init,
+ },
+};
+
+DEFINE_TYPES(iosb_info_types)
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index f84cc68..b6206ef 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -16,6 +16,7 @@
*/
#include "qemu/osdep.h"
+#include "exec/address-spaces.h"
#include "migration/vmstate.h"
#include "hw/sysbus.h"
#include "hw/irq.h"
@@ -114,6 +115,9 @@
#define VIA1A_CPUID1 0x04 /* CPU id bit 0 on RBV, others */
#define VIA1A_CPUID2 0x10 /* CPU id bit 0 on RBV, others */
#define VIA1A_CPUID3 0x40 /* CPU id bit 0 on RBV, others */
+#define VIA1A_CPUID_MASK (VIA1A_CPUID0 | VIA1A_CPUID1 | \
+ VIA1A_CPUID2 | VIA1A_CPUID3)
+#define VIA1A_CPUID_Q800 (VIA1A_CPUID0 | VIA1A_CPUID2)
/*
* Info on VIA1B is from Macintosh Family Hardware & MkLinux.
@@ -698,6 +702,12 @@ static void adb_via_send(MOS6522Q800VIA1State *v1s, int state, uint8_t data)
break;
case ADB_STATE_IDLE:
+ ms->b |= VIA1B_vADBInt;
+ adb_autopoll_unblock(adb_bus);
+
+ trace_via1_adb_send("IDLE", data,
+ (ms->b & VIA1B_vADBInt) ? "+" : "-");
+
return;
}
@@ -865,6 +875,159 @@ static void via1_auxmode_update(MOS6522Q800VIA1State *v1s)
if (irq != oldirq) {
trace_via1_auxmode(irq);
qemu_set_irq(v1s->auxmode_irq, irq);
+
+ /*
+ * Clear the ADB interrupt. MacOS can leave VIA1B_vADBInt asserted
+ * (low) if a poll sequence doesn't complete before NetBSD disables
+ * interrupts upon boot. Fortunately NetBSD switches to the so-called
+ * "A/UX" interrupt mode after it initialises, so we can use this as
+ * a convenient place to clear the ADB interrupt for now.
+ */
+ s->b |= VIA1B_vADBInt;
+ }
+}
+
+/*
+ * Addresses and real values for TimeDBRA/TimeSCCB to allow timer calibration
+ * to succeed (NOTE: both values have been multiplied by 3 to cope with the
+ * speed of QEMU execution on a modern host
+ */
+#define MACOS_TIMEDBRA 0xd00
+#define MACOS_TIMESCCB 0xd02
+
+#define MACOS_TIMEDBRA_VALUE (0x2a00 * 3)
+#define MACOS_TIMESCCB_VALUE (0x079d * 3)
+
+static bool via1_is_toolbox_timer_calibrated(void)
+{
+ /*
+ * Indicate whether the MacOS toolbox has been calibrated by checking
+ * for the value of our magic constants
+ */
+ uint16_t timedbra = lduw_be_phys(&address_space_memory, MACOS_TIMEDBRA);
+ uint16_t timesccdb = lduw_be_phys(&address_space_memory, MACOS_TIMESCCB);
+
+ return (timedbra == MACOS_TIMEDBRA_VALUE &&
+ timesccdb == MACOS_TIMESCCB_VALUE);
+}
+
+static void via1_timer_calibration_hack(MOS6522Q800VIA1State *v1s, int addr,
+ uint64_t val, int size)
+{
+ /*
+ * Work around timer calibration to ensure we that we have non-zero and
+ * known good values for TIMEDRBA and TIMESCCDB.
+ *
+ * This works by attempting to detect the reset and calibration sequence
+ * of writes to VIA1
+ */
+ int old_timer_hack_state = v1s->timer_hack_state;
+
+ switch (v1s->timer_hack_state) {
+ case 0:
+ if (addr == VIA_REG_PCR && val == 0x22) {
+ /* VIA_REG_PCR: configure VIA1 edge triggering */
+ v1s->timer_hack_state = 1;
+ }
+ break;
+ case 1:
+ if (addr == VIA_REG_T2CL && val == 0xc) {
+ /* VIA_REG_T2CL: low byte of 1ms counter */
+ if (!via1_is_toolbox_timer_calibrated()) {
+ v1s->timer_hack_state = 2;
+ } else {
+ v1s->timer_hack_state = 0;
+ }
+ }
+ break;
+ case 2:
+ if (addr == VIA_REG_T2CH && val == 0x3) {
+ /*
+ * VIA_REG_T2CH: high byte of 1ms counter (very likely at the
+ * start of SETUPTIMEK)
+ */
+ if (!via1_is_toolbox_timer_calibrated()) {
+ v1s->timer_hack_state = 3;
+ } else {
+ v1s->timer_hack_state = 0;
+ }
+ }
+ break;
+ case 3:
+ if (addr == VIA_REG_IER && val == 0x20) {
+ /*
+ * VIA_REG_IER: update at end of SETUPTIMEK
+ *
+ * Timer calibration has finished: unfortunately the values in
+ * TIMEDBRA (0xd00) and TIMESCCDB (0xd02) are so far out they
+ * cause divide by zero errors.
+ *
+ * Update them with values obtained from a real Q800 but with
+ * a x3 scaling factor which seems to work well
+ */
+ stw_be_phys(&address_space_memory, MACOS_TIMEDBRA,
+ MACOS_TIMEDBRA_VALUE);
+ stw_be_phys(&address_space_memory, MACOS_TIMESCCB,
+ MACOS_TIMESCCB_VALUE);
+
+ v1s->timer_hack_state = 4;
+ }
+ break;
+ case 4:
+ /*
+ * This is the normal post-calibration timer state: we should
+ * generally remain here unless we detect the A/UX calibration
+ * loop, or a write to VIA_REG_PCR suggesting a reset
+ */
+ if (addr == VIA_REG_PCR && val == 0x22) {
+ /* Looks like there has been a reset? */
+ v1s->timer_hack_state = 1;
+ }
+
+ if (addr == VIA_REG_T2CL && val == 0xf0) {
+ /* VIA_REG_T2CL: low byte of counter (A/UX) */
+ v1s->timer_hack_state = 5;
+ }
+ break;
+ case 5:
+ if (addr == VIA_REG_T2CH && val == 0x3c) {
+ /*
+ * VIA_REG_T2CH: high byte of counter (A/UX). We are now extremely
+ * likely to be in the A/UX timer calibration routine, so move to
+ * the next state where we enable the calibration hack.
+ */
+ v1s->timer_hack_state = 6;
+ } else if ((addr == VIA_REG_IER && val == 0x20) ||
+ addr == VIA_REG_T2CH) {
+ /* We're doing something else with the timer, not calibration */
+ v1s->timer_hack_state = 0;
+ }
+ break;
+ case 6:
+ if ((addr == VIA_REG_IER && val == 0x20) || addr == VIA_REG_T2CH) {
+ /* End of A/UX timer calibration routine, or another write */
+ v1s->timer_hack_state = 7;
+ } else {
+ v1s->timer_hack_state = 0;
+ }
+ break;
+ case 7:
+ /*
+ * This is the normal post-calibration timer state once both the
+ * MacOS toolbox and A/UX have been calibrated, until we see a write
+ * to VIA_REG_PCR to suggest a reset
+ */
+ if (addr == VIA_REG_PCR && val == 0x22) {
+ /* Looks like there has been a reset? */
+ v1s->timer_hack_state = 1;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if (old_timer_hack_state != v1s->timer_hack_state) {
+ trace_via1_timer_hack_state(v1s->timer_hack_state);
}
}
@@ -872,9 +1035,36 @@ static uint64_t mos6522_q800_via1_read(void *opaque, hwaddr addr, unsigned size)
{
MOS6522Q800VIA1State *s = MOS6522_Q800_VIA1(opaque);
MOS6522State *ms = MOS6522(s);
+ uint64_t ret;
+ int64_t now;
addr = (addr >> 9) & 0xf;
- return mos6522_read(ms, addr, size);
+ ret = mos6522_read(ms, addr, size);
+ switch (addr) {
+ case VIA_REG_A:
+ case VIA_REG_ANH:
+ /* Quadra 800 Id */
+ ret = (ret & ~VIA1A_CPUID_MASK) | VIA1A_CPUID_Q800;
+ break;
+ case VIA_REG_T2CH:
+ if (s->timer_hack_state == 6) {
+ /*
+ * The A/UX timer calibration loop runs continuously until 2
+ * consecutive iterations differ by at least 0x492 timer ticks.
+ * Modern hosts execute the timer calibration loop so fast that
+ * this situation never occurs causing a hang on boot. Use a
+ * similar method to Shoebill which is to randomly add 0x500 to
+ * the T2 counter value during calibration to enable it to
+ * eventually succeed.
+ */
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ if (now & 1) {
+ ret += 0x5;
+ }
+ }
+ break;
+ }
+ return ret;
}
static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
@@ -882,8 +1072,13 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
{
MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
MOS6522State *ms = MOS6522(v1s);
+ int oldstate, state;
+ int oldsr = ms->sr;
addr = (addr >> 9) & 0xf;
+
+ via1_timer_calibration_hack(v1s, addr, val, size);
+
mos6522_write(ms, addr, val, size);
switch (addr) {
@@ -894,6 +1089,38 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
v1s->last_b = ms->b;
break;
+
+ case VIA_REG_SR:
+ {
+ /*
+ * NetBSD assumes it can send its first ADB command after sending
+ * the ADB_BUSRESET command in ADB_STATE_NEW without changing the
+ * state back to ADB_STATE_IDLE first as detailed in the ADB
+ * protocol.
+ *
+ * Add a workaround to detect this condition at the start of ADB
+ * enumeration and send the next command written to SR after a
+ * ADB_BUSRESET onto the bus regardless, even if we don't detect a
+ * state transition to ADB_STATE_NEW.
+ *
+ * Note that in my tests the NetBSD state machine takes one ADB
+ * operation to recover which means the probe for an ADB device at
+ * address 1 always fails. However since the first device is at
+ * address 2 then this will work fine, without having to come up
+ * with a more complicated and invasive solution.
+ */
+ oldstate = (v1s->last_b & VIA1B_vADB_StateMask) >>
+ VIA1B_vADB_StateShift;
+ state = (ms->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift;
+
+ if (oldstate == ADB_STATE_NEW && state == ADB_STATE_NEW &&
+ (ms->acr & VIA1ACR_vShiftOut) &&
+ oldsr == 0 /* ADB_BUSRESET */) {
+ trace_via1_adb_netbsd_enum_hack();
+ adb_via_send(v1s, state, ms->sr);
+ }
+ }
+ break;
}
}
@@ -996,6 +1223,9 @@ static void mos6522_q800_via1_reset_hold(Object *obj)
adb_set_autopoll_enabled(adb_bus, true);
v1s->cmd = REG_EMPTY;
v1s->alt = REG_EMPTY;
+
+ /* Timer calibration hack */
+ v1s->timer_hack_state = 0;
}
static void mos6522_q800_via1_realize(DeviceState *dev, Error **errp)
@@ -1088,6 +1318,8 @@ static const VMStateDescription vmstate_q800_via1 = {
VMSTATE_INT64(next_second, MOS6522Q800VIA1State),
VMSTATE_TIMER_PTR(sixty_hz_timer, MOS6522Q800VIA1State),
VMSTATE_INT64(next_sixty_hz, MOS6522Q800VIA1State),
+ /* Timer hack */
+ VMSTATE_INT32(timer_hack_state, MOS6522Q800VIA1State),
VMSTATE_END_OF_LIST()
}
};
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 88ecab8..3365931 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -20,6 +20,8 @@ system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_ras.c'))
# Mac devices
system_ss.add(when: 'CONFIG_MOS6522', if_true: files('mos6522.c'))
+system_ss.add(when: 'CONFIG_DJMEMC', if_true: files('djmemc.c'))
+system_ss.add(when: 'CONFIG_IOSB', if_true: files('iosb.c'))
# virt devices
system_ss.add(when: 'CONFIG_VIRT_CTRL', if_true: files('virt_ctrl.c'))
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index bc87cd3..24ba7cc 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -271,7 +271,9 @@ via1_rtc_cmd_pram_sect_write(int sector, int offset, int addr, int value) "secto
via1_adb_send(const char *state, uint8_t data, const char *vadbint) "state %s data=0x%02x vADBInt=%s"
via1_adb_receive(const char *state, uint8_t data, const char *vadbint, int status, int index, int size) "state %s data=0x%02x vADBInt=%s status=0x%x index=%d size=%d"
via1_adb_poll(uint8_t data, const char *vadbint, int status, int index, int size) "data=0x%02x vADBInt=%s status=0x%x index=%d size=%d"
+via1_adb_netbsd_enum_hack(void) "using NetBSD enum hack"
via1_auxmode(int mode) "setting auxmode to %d"
+via1_timer_hack_state(int state) "setting timer_hack_state to %d"
# grlib_ahb_apb_pnp.c
grlib_ahb_pnp_read(uint64_t addr, unsigned size, uint32_t value) "AHB PnP read addr:0x%03"PRIx64" size:%u data:0x%08x"
@@ -301,3 +303,11 @@ virt_ctrl_instance_init(void *dev) "ctrl: %p"
lasi_chip_mem_valid(uint64_t addr, uint32_t val) "access to addr 0x%"PRIx64" is %d"
lasi_chip_read(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
lasi_chip_write(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
+
+# djmemc.c
+djmemc_read(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRIx64" size=%u"
+djmemc_write(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRIx64" size=%u"
+
+# iosb.c
+iosb_read(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRIx64" size=%u"
+iosb_write(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRIx64" size=%u"
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 57427a3..e8e1661 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -313,8 +313,8 @@ fail:
/* Queue might not be ready for start */
continue;
}
- int r = vhost_net_set_backend(&net->dev, &file);
- assert(r >= 0);
+ int ret = vhost_net_set_backend(&net->dev, &file);
+ assert(ret >= 0);
}
}
if (net->nc->info->poll) {
@@ -629,8 +629,8 @@ err_start:
if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
file.fd = VHOST_FILE_UNBIND;
file.index = idx;
- int r = vhost_net_set_backend(&net->dev, &file);
- assert(r >= 0);
+ int ret = vhost_net_set_backend(&net->dev, &file);
+ assert(ret >= 0);
}
vhost_dev_stop(&net->dev, vdev, false);
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
index 7f6cc2f..f2bdc05 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -227,7 +227,7 @@ int usb_desc_endpoint(const USBDescEndpoint *ep, int flags,
}
if (superlen) {
- USBDescriptor *d = (void *)(dest + bLength);
+ d = (void *)(dest + bLength);
d->bLength = 0x06;
d->bDescriptorType = USB_DT_ENDPOINT_COMPANION;
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index a6b50db..5703e0e 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -402,7 +402,7 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p,
{
unsigned int n = index - 1;
USBHubPort *port;
- USBDevice *dev;
+ USBDevice *pdev;
trace_usb_hub_set_port_feature(s->dev.addr, index,
feature_name(value));
@@ -411,7 +411,7 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p,
goto fail;
}
port = &s->ports[n];
- dev = port->port.dev;
+ pdev = port->port.dev;
switch(value) {
case PORT_SUSPEND:
port->wPortStatus |= PORT_STAT_SUSPEND;
@@ -419,8 +419,8 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p,
case PORT_RESET:
usb_hub_port_set(port, PORT_STAT_RESET);
usb_hub_port_clear(port, PORT_STAT_RESET);
- if (dev && dev->attached) {
- usb_device_reset(dev);
+ if (pdev && pdev->attached) {
+ usb_device_reset(pdev);
usb_hub_port_set(port, PORT_STAT_ENABLE);
}
usb_wakeup(s->intr, 0);
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index e3bcffb..a496c81 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -403,7 +403,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
struct usb_msd_cbw cbw;
uint8_t devep = p->ep->nr;
SCSIDevice *scsi_dev;
- uint32_t len;
+ int len;
if (s->needs_reset) {
p->status = USB_RET_STALL;
@@ -465,7 +465,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
usb_msd_copy_data(s, p);
}
if (le32_to_cpu(s->csw.residue)) {
- int len = p->iov.size - p->actual_length;
+ len = p->iov.size - p->actual_length;
if (len) {
usb_packet_skip(p, len);
if (len > s->data_len) {
@@ -526,7 +526,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
usb_msd_copy_data(s, p);
}
if (le32_to_cpu(s->csw.residue)) {
- int len = p->iov.size - p->actual_length;
+ len = p->iov.size - p->actual_length;
if (len) {
usb_packet_skip(p, len);
if (len > s->data_len) {
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 324177a..4b60114 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -217,10 +217,10 @@ enum {
(((data) >> field##_SHIFT) & field##_MASK)
#define set_field(data, newval, field) do { \
- uint32_t val = *data; \
- val &= ~(field##_MASK << field##_SHIFT); \
- val |= ((newval) & field##_MASK) << field##_SHIFT; \
- *data = val; \
+ uint32_t val_ = *data; \
+ val_ &= ~(field##_MASK << field##_SHIFT); \
+ val_ |= ((newval) & field##_MASK) << field##_SHIFT; \
+ *data = val_; \
} while (0)
typedef enum EPType {
@@ -1894,7 +1894,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
}
if (epctx->retry) {
- XHCITransfer *xfer = epctx->retry;
+ xfer = epctx->retry;
trace_usb_xhci_xfer_retry(xfer);
assert(xfer->running_retry);
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index f500db8..d7060a4 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -1010,7 +1010,7 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd)
* Speeds are defined in linux/usb/ch9.h, file not included
* due to name conflicts.
*/
- int rc = ioctl(hostfd, USBDEVFS_GET_SPEED, NULL);
+ rc = ioctl(hostfd, USBDEVFS_GET_SPEED, NULL);
switch (rc) {
case 1: /* low */
libusb_speed = LIBUSB_SPEED_LOW;
diff --git a/hw/vfio/display.c b/hw/vfio/display.c
index bec864f..837d9e6 100644
--- a/hw/vfio/display.c
+++ b/hw/vfio/display.c
@@ -243,6 +243,8 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev,
dmabuf->dmabuf_id = plane.dmabuf_id;
dmabuf->buf.width = plane.width;
dmabuf->buf.height = plane.height;
+ dmabuf->buf.backing_width = plane.width;
+ dmabuf->buf.backing_height = plane.height;
dmabuf->buf.stride = plane.stride;
dmabuf->buf.fourcc = plane.drm_format;
dmabuf->buf.modifier = plane.drm_format_mod;
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 3b2ca3c..898296f 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -369,12 +369,56 @@ static void vfio_msi_interrupt(void *opaque)
notify(&vdev->pdev, nr);
}
+/*
+ * Get MSI-X enabled, but no vector enabled, by setting vector 0 with an invalid
+ * fd to kernel.
+ */
+static int vfio_enable_msix_no_vec(VFIOPCIDevice *vdev)
+{
+ g_autofree struct vfio_irq_set *irq_set = NULL;
+ int ret = 0, argsz;
+ int32_t *fd;
+
+ argsz = sizeof(*irq_set) + sizeof(*fd);
+
+ irq_set = g_malloc0(argsz);
+ irq_set->argsz = argsz;
+ irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
+ VFIO_IRQ_SET_ACTION_TRIGGER;
+ irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
+ irq_set->start = 0;
+ irq_set->count = 1;
+ fd = (int32_t *)&irq_set->data;
+ *fd = -1;
+
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
+
+ return ret;
+}
+
static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix)
{
struct vfio_irq_set *irq_set;
int ret = 0, i, argsz;
int32_t *fds;
+ /*
+ * If dynamic MSI-X allocation is supported, the vectors to be allocated
+ * and enabled can be scattered. Before kernel enabling MSI-X, setting
+ * nr_vectors causes all these vectors to be allocated on host.
+ *
+ * To keep allocation as needed, use vector 0 with an invalid fd to get
+ * MSI-X enabled first, then set vectors with a potentially sparse set of
+ * eventfds to enable interrupts only when enabled in guest.
+ */
+ if (msix && !vdev->msix->noresize) {
+ ret = vfio_enable_msix_no_vec(vdev);
+
+ if (ret) {
+ return ret;
+ }
+ }
+
argsz = sizeof(*irq_set) + (vdev->nr_vectors * sizeof(*fds));
irq_set = g_malloc0(argsz);
@@ -470,6 +514,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
VFIOPCIDevice *vdev = VFIO_PCI(pdev);
VFIOMSIVector *vector;
int ret;
+ bool resizing = !!(vdev->nr_vectors < nr + 1);
trace_vfio_msix_vector_do_use(vdev->vbasedev.name, nr);
@@ -512,33 +557,42 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
}
/*
- * We don't want to have the host allocate all possible MSI vectors
- * for a device if they're not in use, so we shutdown and incrementally
- * increase them as needed.
+ * When dynamic allocation is not supported, we don't want to have the
+ * host allocate all possible MSI vectors for a device if they're not
+ * in use, so we shutdown and incrementally increase them as needed.
+ * nr_vectors represents the total number of vectors allocated.
+ *
+ * When dynamic allocation is supported, let the host only allocate
+ * and enable a vector when it is in use in guest. nr_vectors represents
+ * the upper bound of vectors being enabled (but not all of the ranges
+ * is allocated or enabled).
*/
- if (vdev->nr_vectors < nr + 1) {
+ if (resizing) {
vdev->nr_vectors = nr + 1;
- if (!vdev->defer_kvm_irq_routing) {
+ }
+
+ if (!vdev->defer_kvm_irq_routing) {
+ if (vdev->msix->noresize && resizing) {
vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
ret = vfio_enable_vectors(vdev, true);
if (ret) {
error_report("vfio: failed to enable vectors, %d", ret);
}
- }
- } else {
- Error *err = NULL;
- int32_t fd;
-
- if (vector->virq >= 0) {
- fd = event_notifier_get_fd(&vector->kvm_interrupt);
} else {
- fd = event_notifier_get_fd(&vector->interrupt);
- }
+ Error *err = NULL;
+ int32_t fd;
- if (vfio_set_irq_signaling(&vdev->vbasedev,
- VFIO_PCI_MSIX_IRQ_INDEX, nr,
- VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err)) {
- error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
+ if (vector->virq >= 0) {
+ fd = event_notifier_get_fd(&vector->kvm_interrupt);
+ } else {
+ fd = event_notifier_get_fd(&vector->interrupt);
+ }
+
+ if (vfio_set_irq_signaling(&vdev->vbasedev,
+ VFIO_PCI_MSIX_IRQ_INDEX, nr,
+ VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err)) {
+ error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
+ }
}
}
@@ -608,6 +662,8 @@ static void vfio_commit_kvm_msi_virq_batch(VFIOPCIDevice *vdev)
static void vfio_msix_enable(VFIOPCIDevice *vdev)
{
+ int ret;
+
vfio_disable_interrupts(vdev);
vdev->msi_vectors = g_new0(VFIOMSIVector, vdev->msix->entries);
@@ -630,8 +686,6 @@ static void vfio_msix_enable(VFIOPCIDevice *vdev)
vfio_commit_kvm_msi_virq_batch(vdev);
if (vdev->nr_vectors) {
- int ret;
-
ret = vfio_enable_vectors(vdev, true);
if (ret) {
error_report("vfio: failed to enable vectors, %d", ret);
@@ -645,13 +699,14 @@ static void vfio_msix_enable(VFIOPCIDevice *vdev)
* MSI-X capability, but leaves the vector table masked. We therefore
* can't rely on a vector_use callback (from request_irq() in the guest)
* to switch the physical device into MSI-X mode because that may come a
- * long time after pci_enable_msix(). This code enables vector 0 with
- * triggering to userspace, then immediately release the vector, leaving
- * the physical device with no vectors enabled, but MSI-X enabled, just
- * like the guest view.
+ * long time after pci_enable_msix(). This code sets vector 0 with an
+ * invalid fd to make the physical device MSI-X enabled, but with no
+ * vectors enabled, just like the guest view.
*/
- vfio_msix_vector_do_use(&vdev->pdev, 0, NULL, NULL);
- vfio_msix_vector_release(&vdev->pdev, 0);
+ ret = vfio_enable_msix_no_vec(vdev);
+ if (ret) {
+ error_report("vfio: failed to enable MSI-X, %d", ret);
+ }
}
trace_vfio_msix_enable(vdev->vbasedev.name);
@@ -1493,7 +1548,9 @@ static void vfio_msix_early_setup(VFIOPCIDevice *vdev, Error **errp)
uint8_t pos;
uint16_t ctrl;
uint32_t table, pba;
- int fd = vdev->vbasedev.fd;
+ int ret, fd = vdev->vbasedev.fd;
+ struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info),
+ .index = VFIO_PCI_MSIX_IRQ_INDEX };
VFIOMSIXInfo *msix;
pos = pci_find_capability(&vdev->pdev, PCI_CAP_ID_MSIX);
@@ -1530,6 +1587,15 @@ static void vfio_msix_early_setup(VFIOPCIDevice *vdev, Error **errp)
msix->pba_offset = pba & ~PCI_MSIX_FLAGS_BIRMASK;
msix->entries = (ctrl & PCI_MSIX_FLAGS_QSIZE) + 1;
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "failed to get MSI-X irq info");
+ g_free(msix);
+ return;
+ }
+
+ msix->noresize = !!(irq_info.flags & VFIO_IRQ_INFO_NORESIZE);
+
/*
* Test the size of the pba_offset variable and catch if it extends outside
* of the specified BAR. If it is the case, we need to apply a hardware
@@ -1562,7 +1628,8 @@ static void vfio_msix_early_setup(VFIOPCIDevice *vdev, Error **errp)
}
trace_vfio_msix_early_setup(vdev->vbasedev.name, pos, msix->table_bar,
- msix->table_offset, msix->entries);
+ msix->table_offset, msix->entries,
+ msix->noresize);
vdev->msix = msix;
vfio_pci_fixup_msix_region(vdev);
@@ -2826,7 +2893,7 @@ static void vfio_populate_device(VFIOPCIDevice *vdev, Error **errp)
}
}
-static void vfio_put_device(VFIOPCIDevice *vdev)
+static void vfio_pci_put_device(VFIOPCIDevice *vdev)
{
g_free(vdev->vbasedev.name);
g_free(vdev->msix);
@@ -3317,7 +3384,7 @@ static void vfio_instance_finalize(Object *obj)
*
* g_free(vdev->igd_opregion);
*/
- vfio_put_device(vdev);
+ vfio_pci_put_device(vdev);
vfio_put_group(group);
}
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index 2d83609..0d89eb7 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -113,6 +113,7 @@ typedef struct VFIOMSIXInfo {
uint32_t table_offset;
uint32_t pba_offset;
unsigned long *pending;
+ bool noresize;
} VFIOMSIXInfo;
#define TYPE_VFIO_PCI "vfio-pci"
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index e64ca4a..0ba3c5a 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -27,7 +27,7 @@ vfio_vga_read(uint64_t addr, int size, uint64_t data) " (0x%"PRIx64", %d) = 0x%"
vfio_pci_read_config(const char *name, int addr, int len, int val) " (%s, @0x%x, len=0x%x) 0x%x"
vfio_pci_write_config(const char *name, int addr, int val, int len) " (%s, @0x%x, 0x%x, len=0x%x)"
vfio_msi_setup(const char *name, int pos) "%s PCI MSI CAP @0x%x"
-vfio_msix_early_setup(const char *name, int pos, int table_bar, int offset, int entries) "%s PCI MSI-X CAP @0x%x, BAR %d, offset 0x%x, entries %d"
+vfio_msix_early_setup(const char *name, int pos, int table_bar, int offset, int entries, bool noresize) "%s PCI MSI-X CAP @0x%x, BAR %d, offset 0x%x, entries %d, noresize %d"
vfio_check_pcie_flr(const char *name) "%s Supports FLR via PCIe cap"
vfio_check_pm_reset(const char *name) "%s Supports PM reset"
vfio_check_af_flr(const char *name) "%s Supports FLR via AF cap"
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index e2f6ffb..9cfac40 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -66,12 +66,12 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
uint64_t mfirst, uint64_t mlast,
uint64_t rfirst, uint64_t rlast)
{
- vhost_log_chunk_t *log = dev->log->log;
+ vhost_log_chunk_t *dev_log = dev->log->log;
uint64_t start = MAX(mfirst, rfirst);
uint64_t end = MIN(mlast, rlast);
- vhost_log_chunk_t *from = log + start / VHOST_LOG_CHUNK;
- vhost_log_chunk_t *to = log + end / VHOST_LOG_CHUNK + 1;
+ vhost_log_chunk_t *from = dev_log + start / VHOST_LOG_CHUNK;
+ vhost_log_chunk_t *to = dev_log + end / VHOST_LOG_CHUNK + 1;
uint64_t addr = QEMU_ALIGN_DOWN(start, VHOST_LOG_CHUNK);
if (end < start) {
@@ -549,7 +549,7 @@ static void vhost_commit(MemoryListener *listener)
changed = true;
} else {
/* Same size, lets check the contents */
- for (int i = 0; i < n_old_sections; i++) {
+ for (i = 0; i < n_old_sections; i++) {
if (!MemoryRegionSection_eq(&old_sections[i],
&dev->mem_sections[i])) {
changed = true;
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index edbc0da..abebd00 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -780,15 +780,15 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
pci_cfg_data),
sizeof cfg->pci_cfg_data)) {
uint32_t off;
- uint32_t len;
+ uint32_t caplen;
cfg = (void *)(proxy->pci_dev.config + proxy->config_cap);
off = le32_to_cpu(cfg->cap.offset);
- len = le32_to_cpu(cfg->cap.length);
+ caplen = le32_to_cpu(cfg->cap.length);
- if (len == 1 || len == 2 || len == 4) {
- assert(len <= sizeof cfg->pci_cfg_data);
- virtio_address_space_write(proxy, off, cfg->pci_cfg_data, len);
+ if (caplen == 1 || caplen == 2 || caplen == 4) {
+ assert(caplen <= sizeof cfg->pci_cfg_data);
+ virtio_address_space_write(proxy, off, cfg->pci_cfg_data, caplen);
}
}
}
@@ -804,15 +804,15 @@ static uint32_t virtio_read_config(PCIDevice *pci_dev,
pci_cfg_data),
sizeof cfg->pci_cfg_data)) {
uint32_t off;
- uint32_t len;
+ uint32_t caplen;
cfg = (void *)(proxy->pci_dev.config + proxy->config_cap);
off = le32_to_cpu(cfg->cap.offset);
- len = le32_to_cpu(cfg->cap.length);
+ caplen = le32_to_cpu(cfg->cap.length);
- if (len == 1 || len == 2 || len == 4) {
- assert(len <= sizeof cfg->pci_cfg_data);
- virtio_address_space_read(proxy, off, cfg->pci_cfg_data, len);
+ if (caplen == 1 || caplen == 2 || caplen == 4) {
+ assert(caplen <= sizeof cfg->pci_cfg_data);
+ virtio_address_space_read(proxy, off, cfg->pci_cfg_data, caplen);
}
}
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 8a765e7..4e7bd63 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -29,6 +29,7 @@
typedef struct NBDExport NBDExport;
typedef struct NBDClient NBDClient;
typedef struct NBDClientConnection NBDClientConnection;
+typedef struct NBDMetaContexts NBDMetaContexts;
extern const BlockExportDriver blk_exp_nbd;
@@ -76,6 +77,7 @@ typedef struct NBDRequest {
uint16_t flags; /* NBD_CMD_FLAG_* */
uint16_t type; /* NBD_CMD_* */
NBDMode mode; /* Determines which network representation to use */
+ NBDMetaContexts *contexts; /* Used by NBD_CMD_BLOCK_STATUS */
} NBDRequest;
typedef struct NBDSimpleReply {
@@ -389,7 +391,8 @@ int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
Error **errp);
int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
- NBDReply *reply, Error **errp);
+ NBDReply *reply, NBDMode mode,
+ Error **errp);
int nbd_client(int fd);
int nbd_disconnect(int fd);
int nbd_errno_to_system_errno(int err);
diff --git a/include/hw/audio/asc.h b/include/hw/audio/asc.h
new file mode 100644
index 0000000..4741f92
--- /dev/null
+++ b/include/hw/audio/asc.h
@@ -0,0 +1,86 @@
+/*
+ * QEMU Apple Sound Chip emulation
+ *
+ * Apple Sound Chip (ASC) 344S0063
+ * Enhanced Apple Sound Chip (EASC) 343S1063
+ *
+ * Copyright (c) 2012-2018 Laurent Vivier <laurent@vivier.eu>
+ * Copyright (c) 2022 Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_AUDIO_ASC_H
+#define HW_AUDIO_ASC_H
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "audio/audio.h"
+
+#define ASC_FREQ 22257
+
+enum {
+ ASC_TYPE_ASC = 0, /* original discrete Apple Sound Chip */
+ ASC_TYPE_EASC = 1 /* discrete Enhanced Apple Sound Chip */
+};
+
+#define ASC_FIFO_OFFSET 0x0
+#define ASC_FIFO_SIZE 0x400
+
+#define ASC_REG_OFFSET 0x800
+#define ASC_REG_SIZE 0x60
+
+#define ASC_EXTREG_OFFSET 0xf00
+#define ASC_EXTREG_SIZE 0x20
+
+typedef struct ASCFIFOState {
+ int index;
+
+ MemoryRegion mem_fifo;
+ uint8_t fifo[ASC_FIFO_SIZE];
+ uint8_t int_status;
+
+ int cnt;
+ int wptr;
+ int rptr;
+
+ MemoryRegion mem_extregs;
+ uint8_t extregs[ASC_EXTREG_SIZE];
+
+ int xa_cnt;
+ uint8_t xa_val;
+ uint8_t xa_flags;
+ int16_t xa_last[2];
+} ASCFIFOState;
+
+struct ASCState {
+ SysBusDevice parent_obj;
+
+ uint8_t type;
+ MemoryRegion asc;
+ MemoryRegion mem_fifo;
+ MemoryRegion mem_regs;
+ MemoryRegion mem_extregs;
+
+ QEMUSoundCard card;
+ SWVoiceOut *voice;
+ uint8_t *mixbuf;
+ int samples;
+ int shift;
+
+ uint8_t *silentbuf;
+
+ /* Time when we were last able to generate samples */
+ int64_t fifo_empty_ns;
+
+ qemu_irq irq;
+
+ ASCFIFOState fifos[2];
+
+ uint8_t regs[ASC_REG_SIZE];
+};
+
+#define TYPE_ASC "apple-sound-chip"
+OBJECT_DECLARE_SIMPLE_TYPE(ASCState, ASC)
+
+#endif
diff --git a/include/hw/audio/soundhw.h b/include/hw/audio/soundhw.h
index 270717a..474c5ff 100644
--- a/include/hw/audio/soundhw.h
+++ b/include/hw/audio/soundhw.h
@@ -8,6 +8,6 @@ void deprecated_register_soundhw(const char *name, const char *descr,
void soundhw_init(void);
void show_valid_soundhw(void);
-void select_soundhw(const char *optarg, const char *audiodev);
+void select_soundhw(const char *name, const char *audiodev);
#endif
diff --git a/include/hw/block/swim.h b/include/hw/block/swim.h
index 9b3dcb0..5f567e8 100644
--- a/include/hw/block/swim.h
+++ b/include/hw/block/swim.h
@@ -43,25 +43,22 @@ typedef struct FDrive {
} FDrive;
struct SWIMCtrl {
- MemoryRegion iomem;
+ MemoryRegion swim;
+ MemoryRegion iwm;
+ MemoryRegion ism;
FDrive drives[SWIM_MAX_FD];
int mode;
/* IWM mode */
int iwm_switch;
- uint16_t regs[8];
-#define IWM_PH0 0
-#define IWM_PH1 1
-#define IWM_PH2 2
-#define IWM_PH3 3
-#define IWM_MTR 4
-#define IWM_DRIVE 5
-#define IWM_Q6 6
-#define IWM_Q7 7
- uint8_t iwm_data;
- uint8_t iwm_mode;
+ uint8_t iwm_latches;
+ uint8_t iwmregs[8];
/* SWIM mode */
+ uint8_t ismregs[16];
uint8_t swim_phase;
uint8_t swim_mode;
+ uint8_t swim_status;
+ uint8_t pram[16];
+ uint8_t pram_idx;
SWIMBus bus;
};
diff --git a/include/hw/m68k/q800-glue.h b/include/hw/m68k/q800-glue.h
index a35efc1..ceb916d 100644
--- a/include/hw/m68k/q800-glue.h
+++ b/include/hw/m68k/q800-glue.h
@@ -35,7 +35,7 @@ struct GLUEState {
M68kCPU *cpu;
uint8_t ipr;
uint8_t auxmode;
- qemu_irq irqs[1];
+ qemu_irq irqs[2];
QEMUTimer *nmi_release;
};
@@ -44,7 +44,9 @@ struct GLUEState {
#define GLUE_IRQ_IN_SONIC 2
#define GLUE_IRQ_IN_ESCC 3
#define GLUE_IRQ_IN_NMI 4
+#define GLUE_IRQ_IN_ASC 5
#define GLUE_IRQ_NUBUS_9 0
+#define GLUE_IRQ_ASC 1
#endif
diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index b3d77f1..a9661f6 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -36,6 +36,9 @@
#include "hw/block/swim.h"
#include "hw/nubus/mac-nubus-bridge.h"
#include "hw/display/macfb.h"
+#include "hw/misc/djmemc.h"
+#include "hw/misc/iosb.h"
+#include "hw/audio/asc.h"
/*
* The main Q800 machine
@@ -44,8 +47,10 @@
struct Q800MachineState {
MachineState parent_obj;
+ bool easc;
M68kCPU cpu;
MemoryRegion rom;
+ MemoryRegion rom_alias;
GLUEState glue;
MOS6522Q800VIA1State via1;
MOS6522Q800VIA2State via2;
@@ -56,8 +61,14 @@ struct Q800MachineState {
Swim swim;
MacNubusBridge mac_nubus_bridge;
MacfbNubusState macfb;
+ DJMEMCState djmemc;
+ IOSBState iosb;
+ ASCState asc;
+ MemoryRegion ramio;
MemoryRegion macio;
MemoryRegion macio_alias;
+ MemoryRegion machine_id;
+ MemoryRegion escc_alias;
};
#define TYPE_Q800_MACHINE MACHINE_TYPE_NAME("q800")
diff --git a/include/hw/misc/djmemc.h b/include/hw/misc/djmemc.h
new file mode 100644
index 0000000..82d4e4a
--- /dev/null
+++ b/include/hw/misc/djmemc.h
@@ -0,0 +1,30 @@
+/*
+ * djMEMC, macintosh memory and interrupt controller
+ * (Quadra 610/650/800 & Centris 610/650)
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MISC_DJMEMC_H
+#define HW_MISC_DJMEMC_H
+
+#include "hw/sysbus.h"
+
+#define DJMEMC_SIZE 0x2000
+#define DJMEMC_NUM_REGS (0x38 / sizeof(uint32_t))
+
+#define DJMEMC_MAXBANKS 10
+
+struct DJMEMCState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mem_regs;
+
+ /* Memory controller */
+ uint32_t regs[DJMEMC_NUM_REGS];
+};
+
+#define TYPE_DJMEMC "djMEMC"
+OBJECT_DECLARE_SIMPLE_TYPE(DJMEMCState, DJMEMC);
+
+#endif
diff --git a/include/hw/misc/iosb.h b/include/hw/misc/iosb.h
new file mode 100644
index 0000000..377f8ca
--- /dev/null
+++ b/include/hw/misc/iosb.h
@@ -0,0 +1,25 @@
+/*
+ * QEMU IOSB emulation
+ *
+ * Copyright (c) 2019 Laurent Vivier
+ * Copyright (c) 2022 Mark Cave-Ayland
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MEM_IOSB_H
+#define HW_MEM_IOSB_H
+
+#define IOSB_REGS 7
+
+struct IOSBState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mem_regs;
+ uint32_t regs[IOSB_REGS];
+};
+
+#define TYPE_IOSB "IOSB"
+OBJECT_DECLARE_SIMPLE_TYPE(IOSBState, IOSB);
+
+#endif
diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h
index 422da43..63cdcf7 100644
--- a/include/hw/misc/mac_via.h
+++ b/include/hw/misc/mac_via.h
@@ -74,6 +74,9 @@ struct MOS6522Q800VIA1State {
int64_t next_second;
QEMUTimer *sixty_hz_timer;
int64_t next_sixty_hz;
+
+ /* SETUPTIMEK hack */
+ int timer_hack_state;
};
diff --git a/include/net/net.h b/include/net/net.h
index 330d285..2fb1c91 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -247,9 +247,9 @@ extern const char *host_net_devices[];
/* from net.c */
extern NetClientStateList net_clients;
-bool netdev_is_modern(const char *optarg);
-void netdev_parse_modern(const char *optarg);
-void net_client_parse(QemuOptsList *opts_list, const char *str);
+bool netdev_is_modern(const char *optstr);
+void netdev_parse_modern(const char *optstr);
+void net_client_parse(QemuOptsList *opts_list, const char *optstr);
void show_netdevs(void);
void net_init_clients(void);
void net_check_clients(void);
diff --git a/include/qemu/atomic128.h b/include/qemu/atomic128.h
index 34554bf..88af6d4 100644
--- a/include/qemu/atomic128.h
+++ b/include/qemu/atomic128.h
@@ -43,8 +43,8 @@
* See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80878
*
* This interpretation is not especially helpful for QEMU.
- * For softmmu, all RAM is always read/write from the hypervisor.
- * For user-only, if the guest doesn't implement such an __atomic_read
+ * For system-mode, all RAM is always read/write from the hypervisor.
+ * For user-mode, if the guest doesn't implement such an __atomic_read
* then the host need not worry about it either.
*
* Moreover, using libatomic is not an option, because its interface is
diff --git a/include/qemu/guest-random.h b/include/qemu/guest-random.h
index 09ff9c2..5060d49 100644
--- a/include/qemu/guest-random.h
+++ b/include/qemu/guest-random.h
@@ -13,16 +13,16 @@
#define QEMU_GUEST_RANDOM_H
/**
- * qemu_guest_random_seed_main(const char *optarg, Error **errp)
- * @optarg: a non-NULL pointer to a C string
+ * qemu_guest_random_seed_main(const char *seedstr, Error **errp)
+ * @seedstr: a non-NULL pointer to a C string
* @errp: an error indicator
*
- * The @optarg value is that which accompanies the -seed argument.
+ * The @seedstr value is that which accompanies the -seed argument.
* This forces qemu_guest_getrandom into deterministic mode.
*
* Returns 0 on success, < 0 on failure while setting *errp.
*/
-int qemu_guest_random_seed_main(const char *optarg, Error **errp);
+int qemu_guest_random_seed_main(const char *seedstr, Error **errp);
/**
* qemu_guest_random_seed_thread_part1(void)
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
index bc0781c..7fdc3a4 100644
--- a/include/qemu/plugin.h
+++ b/include/qemu/plugin.h
@@ -50,7 +50,7 @@ static inline void qemu_plugin_add_opts(void)
qemu_add_opts(&qemu_plugin_opts);
}
-void qemu_plugin_opt_parse(const char *optarg, QemuPluginList *head);
+void qemu_plugin_opt_parse(const char *optstr, QemuPluginList *head);
int qemu_plugin_load_list(QemuPluginList *head, Error **errp);
union qemu_plugin_cb_sig {
@@ -242,7 +242,7 @@ void qemu_plugin_user_postfork(bool is_child);
static inline void qemu_plugin_add_opts(void)
{ }
-static inline void qemu_plugin_opt_parse(const char *optarg,
+static inline void qemu_plugin_opt_parse(const char *optstr,
QemuPluginList *head)
{
error_report("plugin interface not enabled in this build");
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
index 81541e2..02b11a7 100644
--- a/include/qom/object_interfaces.h
+++ b/include/qom/object_interfaces.h
@@ -99,7 +99,7 @@ void user_creatable_add_qapi(ObjectOptions *options, Error **errp);
/**
* user_creatable_parse_str:
- * @optarg: the object definition string as passed on the command line
+ * @str: the object definition string as passed on the command line
* @errp: if an error occurs, a pointer to an area to store the error
*
* Parses the option for the user creatable object with a keyval parser and
@@ -110,14 +110,14 @@ void user_creatable_add_qapi(ObjectOptions *options, Error **errp);
* Returns: ObjectOptions on success, NULL when an error occurred (*errp is set
* then) or help was printed (*errp is not set).
*/
-ObjectOptions *user_creatable_parse_str(const char *optarg, Error **errp);
+ObjectOptions *user_creatable_parse_str(const char *str, Error **errp);
/**
* user_creatable_add_from_str:
- * @optarg: the object definition string as passed on the command line
+ * @str: the object definition string as passed on the command line
* @errp: if an error occurs, a pointer to an area to store the error
*
- * Create an instance of the user creatable object by parsing optarg
+ * Create an instance of the user creatable object by parsing @str
* with a keyval parser and implicit key 'qom-type', converting the
* result to ObjectOptions and calling into qmp_object_add().
*
@@ -126,13 +126,13 @@ ObjectOptions *user_creatable_parse_str(const char *optarg, Error **errp);
* Returns: true when an object was successfully created, false when an error
* occurred (*errp is set then) or help was printed (*errp is not set).
*/
-bool user_creatable_add_from_str(const char *optarg, Error **errp);
+bool user_creatable_add_from_str(const char *str, Error **errp);
/**
* user_creatable_process_cmdline:
- * @optarg: the object definition string as passed on the command line
+ * @cmdline: the object definition string as passed on the command line
*
- * Create an instance of the user creatable object by parsing optarg
+ * Create an instance of the user creatable object by parsing @cmdline
* with a keyval parser and implicit key 'qom-type', converting the
* result to ObjectOptions and calling into qmp_object_add().
*
@@ -141,7 +141,7 @@ bool user_creatable_add_from_str(const char *optarg, Error **errp);
* This function is only meant to be called during command line parsing.
* It exits the process on failure or after printing help.
*/
-void user_creatable_process_cmdline(const char *optarg);
+void user_creatable_process_cmdline(const char *cmdline);
/**
* user_creatable_print_help:
diff --git a/include/semihosting/semihost.h b/include/semihosting/semihost.h
index efd2efa..97d2a2b 100644
--- a/include/semihosting/semihost.h
+++ b/include/semihosting/semihost.h
@@ -66,7 +66,7 @@ const char *semihosting_get_cmdline(void);
void semihosting_arg_fallback(const char *file, const char *cmd);
/* for vl.c hooks */
void qemu_semihosting_enable(void);
-int qemu_semihosting_config_options(const char *opt);
+int qemu_semihosting_config_options(const char *optstr);
void qemu_semihosting_chardev_init(void);
void qemu_semihosting_console_init(Chardev *);
#endif /* CONFIG_USER_ONLY */
diff --git a/include/semihosting/softmmu-uaccess.h b/include/semihosting/uaccess.h
index 4f08dfc..3963eaf 100644
--- a/include/semihosting/softmmu-uaccess.h
+++ b/include/semihosting/uaccess.h
@@ -7,8 +7,12 @@
* This code is licensed under the GPL
*/
-#ifndef SEMIHOSTING_SOFTMMU_UACCESS_H
-#define SEMIHOSTING_SOFTMMU_UACCESS_H
+#ifndef SEMIHOSTING_UACCESS_H
+#define SEMIHOSTING_UACCESS_H
+
+#ifdef CONFIG_USER_ONLY
+#error Cannot include semihosting/uaccess.h from user emulation
+#endif
#include "cpu.h"
@@ -42,18 +46,18 @@
#define put_user_ual(arg, p) put_user_u32(arg, p)
-void *softmmu_lock_user(CPUArchState *env, target_ulong addr,
+void *uaccess_lock_user(CPUArchState *env, target_ulong addr,
target_ulong len, bool copy);
-#define lock_user(type, p, len, copy) softmmu_lock_user(env, p, len, copy)
+#define lock_user(type, p, len, copy) uaccess_lock_user(env, p, len, copy)
-char *softmmu_lock_user_string(CPUArchState *env, target_ulong addr);
-#define lock_user_string(p) softmmu_lock_user_string(env, p)
+char *uaccess_lock_user_string(CPUArchState *env, target_ulong addr);
+#define lock_user_string(p) uaccess_lock_user_string(env, p)
-void softmmu_unlock_user(CPUArchState *env, void *p,
+void uaccess_unlock_user(CPUArchState *env, void *p,
target_ulong addr, target_ulong len);
-#define unlock_user(s, args, len) softmmu_unlock_user(env, s, args, len)
+#define unlock_user(s, args, len) uaccess_unlock_user(env, s, args, len)
-ssize_t softmmu_strlen_user(CPUArchState *env, target_ulong addr);
-#define target_strlen(p) softmmu_strlen_user(env, p)
+ssize_t uaccess_strlen_user(CPUArchState *env, target_ulong addr);
+#define target_strlen(p) uaccess_strlen_user(env, p)
#endif /* SEMIHOSTING_SOFTMMU_UACCESS_H */
diff --git a/softmmu/timers-state.h b/include/sysemu/cpu-timers-internal.h
index 94bb739..94bb739 100644
--- a/softmmu/timers-state.h
+++ b/include/sysemu/cpu-timers-internal.h
diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h
index 4037cd6..4a7c6af 100644
--- a/include/sysemu/hvf.h
+++ b/include/sysemu/hvf.h
@@ -20,13 +20,10 @@
#include "cpu.h"
#ifdef CONFIG_HVF
-uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
- int reg);
extern bool hvf_allowed;
#define hvf_enabled() (hvf_allowed)
#else /* !CONFIG_HVF */
#define hvf_enabled() 0
-#define hvf_get_supported_cpuid(func, idx, reg) 0
#endif /* !CONFIG_HVF */
#endif /* NEED_CPU_H */
diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h
index 6dfdcbb..dff32ae 100644
--- a/include/sysemu/os-posix.h
+++ b/include/sysemu/os-posix.h
@@ -49,8 +49,8 @@ void os_setup_signal_handling(void);
int os_set_daemonize(bool d);
bool is_daemonized(void);
void os_daemonize(void);
-bool os_set_runas(const char *optarg);
-void os_set_chroot(const char *optarg);
+bool os_set_runas(const char *user_id);
+void os_set_chroot(const char *path);
void os_setup_post(void);
int os_mlock(void);
diff --git a/include/sysemu/runstate-action.h b/include/sysemu/runstate-action.h
index cff45a0..db4e309 100644
--- a/include/sysemu/runstate-action.h
+++ b/include/sysemu/runstate-action.h
@@ -11,7 +11,7 @@
#include "qapi/qapi-commands-run-state.h"
-/* in softmmu/runstate-action.c */
+/* in system/runstate-action.c */
extern RebootAction reboot_action;
extern ShutdownAction shutdown_action;
extern PanicAction panic_action;
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 66e3b45..1ee568b 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -17,7 +17,7 @@
#ifdef CONFIG_TPM
-int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
+int tpm_config_parse(QemuOptsList *opts_list, const char *optstr);
int tpm_init(void);
void tpm_cleanup(void);
diff --git a/include/tcg/tcg-op-common.h b/include/tcg/tcg-op-common.h
index a53b159..2048f92 100644
--- a/include/tcg/tcg-op-common.h
+++ b/include/tcg/tcg-op-common.h
@@ -265,7 +265,7 @@ void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx);
*
* See tcg/README for more info about this TCG operation.
*
- * NOTE: In softmmu emulation, direct jumps with goto_tb are only safe within
+ * NOTE: In system emulation, direct jumps with goto_tb are only safe within
* the pages this TB resides in because we don't take care of direct jumps when
* address mapping changes, e.g. in tlb_flush(). In user mode, there's only a
* static address translation, so the destination address is always valid, TBs
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 4331a11..fdcc461 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -755,15 +755,15 @@ int load_flt_binary(struct linux_binprm *bprm, struct image_info *info)
/* Update data segment pointers for all libraries */
for (i=0; i<MAX_SHARED_LIBS; i++) {
if (libinfo[i].loaded) {
- abi_ulong p;
- p = libinfo[i].start_data;
+ abi_ulong seg;
+ seg = libinfo[i].start_data;
for (j=0; j<MAX_SHARED_LIBS; j++) {
- p -= 4;
+ seg -= 4;
/* FIXME - handle put_user() failures */
if (put_user_ual(libinfo[j].loaded
? libinfo[j].start_data
: UNLOADED_LIB,
- p))
+ seg))
return -EFAULT;
}
}
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 8eaf57b..8ccaab7 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -910,16 +910,16 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
}
}
} else {
- int prot = 0;
+ int page_flags = 0;
if (reserved_va && old_size < new_size) {
abi_ulong addr;
for (addr = old_addr + old_size;
addr < old_addr + new_size;
addr++) {
- prot |= page_get_flags(addr);
+ page_flags |= page_get_flags(addr);
}
}
- if (prot == 0) {
+ if (page_flags == 0) {
host_addr = mremap(g2h_untagged(old_addr),
old_size, new_size, flags);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c6ffadd..d49cd31 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5050,8 +5050,8 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
{
void *gspec = argptr;
void *cur_data = host_data;
- const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
- int spec_size = thunk_type_size(arg_type, 0);
+ const argtype dm_arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
+ int spec_size = thunk_type_size(dm_arg_type, 0);
int i;
for (i = 0; i < host_dm->target_count; i++) {
@@ -5059,7 +5059,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
uint32_t next;
int slen;
- thunk_convert(spec, gspec, arg_type, THUNK_HOST);
+ thunk_convert(spec, gspec, dm_arg_type, THUNK_HOST);
slen = strlen((char*)gspec + spec_size) + 1;
next = spec->next;
spec->next = sizeof(*spec) + slen;
@@ -5099,7 +5099,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
uint32_t remaining_data = guest_data_size;
void *cur_data = argptr;
- const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
+ const argtype dm_arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
int nl_size = 12; /* can't use thunk_size due to alignment */
while (1) {
@@ -5111,7 +5111,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
host_dm->flags |= DM_BUFFER_FULL_FLAG;
break;
}
- thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
+ thunk_convert(cur_data, nl, dm_arg_type, THUNK_TARGET);
strcpy(cur_data + nl_size, nl->name);
cur_data += nl->next;
remaining_data -= nl->next;
@@ -5127,8 +5127,8 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
{
struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
void *cur_data = argptr;
- const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
- int spec_size = thunk_type_size(arg_type, 0);
+ const argtype dm_arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
+ int spec_size = thunk_type_size(dm_arg_type, 0);
int i;
for (i = 0; i < host_dm->target_count; i++) {
@@ -5139,7 +5139,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
host_dm->flags |= DM_BUFFER_FULL_FLAG;
break;
}
- thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
+ thunk_convert(cur_data, spec, dm_arg_type, THUNK_TARGET);
strcpy(cur_data + spec_size, (char*)&spec[1]);
cur_data = argptr + spec->next;
spec = (void*)host_dm + host_dm->data_start + next;
@@ -5167,8 +5167,8 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
uint32_t remaining_data = guest_data_size;
void *cur_data = argptr;
- const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
- int vers_size = thunk_type_size(arg_type, 0);
+ const argtype dm_arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
+ int vers_size = thunk_type_size(dm_arg_type, 0);
while (1) {
uint32_t next = vers->next;
@@ -5179,7 +5179,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
host_dm->flags |= DM_BUFFER_FULL_FLAG;
break;
}
- thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
+ thunk_convert(cur_data, vers, dm_arg_type, THUNK_TARGET);
strcpy(cur_data + vers_size, vers->name);
cur_data += vers->next;
remaining_data -= vers->next;
@@ -11177,14 +11177,14 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
}
case TARGET_NR_getcpu:
{
- unsigned cpu, node;
- ret = get_errno(sys_getcpu(arg1 ? &cpu : NULL,
+ unsigned cpuid, node;
+ ret = get_errno(sys_getcpu(arg1 ? &cpuid : NULL,
arg2 ? &node : NULL,
NULL));
if (is_error(ret)) {
return ret;
}
- if (arg1 && put_user_u32(cpu, arg1)) {
+ if (arg1 && put_user_u32(cpuid, arg1)) {
return -TARGET_EFAULT;
}
if (arg2 && put_user_u32(node, arg2)) {
@@ -12339,7 +12339,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
case TARGET_NR_listxattr:
case TARGET_NR_llistxattr:
{
- void *p, *b = 0;
+ void *b = 0;
if (arg2) {
b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
if (!b) {
@@ -12376,7 +12376,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
case TARGET_NR_setxattr:
case TARGET_NR_lsetxattr:
{
- void *p, *n, *v = 0;
+ void *n, *v = 0;
if (arg3) {
v = lock_user(VERIFY_READ, arg3, arg4, 1);
if (!v) {
@@ -12421,7 +12421,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
case TARGET_NR_getxattr:
case TARGET_NR_lgetxattr:
{
- void *p, *n, *v = 0;
+ void *n, *v = 0;
if (arg3) {
v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
if (!v) {
@@ -12466,7 +12466,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
case TARGET_NR_removexattr:
case TARGET_NR_lremovexattr:
{
- void *p, *n;
+ void *n;
p = lock_user_string(arg1);
n = lock_user_string(arg2);
if (p && n) {
diff --git a/meson.build b/meson.build
index 3bb64b5..79aef19 100644
--- a/meson.build
+++ b/meson.build
@@ -3198,7 +3198,7 @@ modules = {}
target_modules = {}
hw_arch = {}
target_arch = {}
-target_softmmu_arch = {}
+target_system_arch = {}
target_user_arch = {}
###############
@@ -3291,7 +3291,7 @@ if have_system
'hw/gpio',
'migration',
'net',
- 'softmmu',
+ 'system',
'ui',
'hw/remote',
]
@@ -3418,7 +3418,7 @@ endif
common_ss.add(files('cpu-common.c'))
specific_ss.add(files('cpu-target.c'))
-subdir('softmmu')
+subdir('system')
# Work around a gcc bug/misfeature wherein constant propagation looks
# through an alias:
@@ -3480,7 +3480,7 @@ modinfo_generate = find_program('scripts/modinfo-generate.py')
modinfo_files = []
block_mods = []
-softmmu_mods = []
+system_mods = []
foreach d, list : modules
if not (d == 'block' ? have_block : have_system)
continue
@@ -3494,7 +3494,7 @@ foreach d, list : modules
if d == 'block'
block_mods += sl
else
- softmmu_mods += sl
+ system_mods += sl
endif
if module_ss.sources() != []
# FIXME: Should use sl.extract_all_objects(recursive: true) as
@@ -3538,7 +3538,7 @@ foreach d, list : target_modules
include_directories: target_inc,
c_args: c_args,
pic: true)
- softmmu_mods += sl
+ system_mods += sl
# FIXME: Should use sl.extract_all_objects(recursive: true) too.
modinfo_files += custom_target(module_name + '.modinfo',
output: module_name + '.modinfo',
@@ -3581,7 +3581,7 @@ block_syms = custom_target('block.syms', output: 'block.syms',
capture: true,
command: [undefsym, nm, '@INPUT@'])
qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
- input: [libqemuutil, softmmu_mods],
+ input: [libqemuutil, system_mods],
capture: true,
command: [undefsym, nm, '@INPUT@'])
@@ -3666,7 +3666,7 @@ common_ss.add(hwcore)
###########
emulator_modules = []
-foreach m : block_mods + softmmu_mods
+foreach m : block_mods + system_mods
emulator_modules += shared_module(m.name(),
build_by_default: true,
name_prefix: '',
@@ -3718,7 +3718,7 @@ foreach target : target_dirs
endif
if target.endswith('-softmmu')
target_type='system'
- t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
+ t = target_system_arch[target_base_arch].apply(config_target, strict: false)
arch_srcs += t.sources()
arch_deps += t.dependencies()
@@ -3797,14 +3797,14 @@ foreach target : target_dirs
execs = [{
'name': 'qemu-system-' + target_name,
'win_subsystem': 'console',
- 'sources': files('softmmu/main.c'),
+ 'sources': files('system/main.c'),
'dependencies': []
}]
if targetos == 'windows' and (sdl.found() or gtk.found())
execs += [{
'name': 'qemu-system-' + target_name + 'w',
'win_subsystem': 'windows',
- 'sources': files('softmmu/main.c'),
+ 'sources': files('system/main.c'),
'dependencies': []
}]
endif
diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c
index bccb351..036ac01 100644
--- a/migration/dirtyrate.c
+++ b/migration/dirtyrate.c
@@ -189,10 +189,9 @@ retry:
return duration;
}
-static bool is_sample_period_valid(int64_t sec)
+static bool is_calc_time_valid(int64_t msec)
{
- if (sec < MIN_FETCH_DIRTYRATE_TIME_SEC ||
- sec > MAX_FETCH_DIRTYRATE_TIME_SEC) {
+ if ((msec < MIN_CALC_TIME_MS) || (msec > MAX_CALC_TIME_MS)) {
return false;
}
@@ -216,7 +215,39 @@ static int dirtyrate_set_state(int *state, int old_state, int new_state)
}
}
-static struct DirtyRateInfo *query_dirty_rate_info(void)
+/* Decimal power of given time unit relative to one second */
+static int time_unit_to_power(TimeUnit time_unit)
+{
+ switch (time_unit) {
+ case TIME_UNIT_SECOND:
+ return 0;
+ case TIME_UNIT_MILLISECOND:
+ return -3;
+ default:
+ assert(false); /* unreachable */
+ return 0;
+ }
+}
+
+static int64_t convert_time_unit(int64_t value, TimeUnit unit_from,
+ TimeUnit unit_to)
+{
+ int power = time_unit_to_power(unit_from) -
+ time_unit_to_power(unit_to);
+ while (power < 0) {
+ value /= 10;
+ power += 1;
+ }
+ while (power > 0) {
+ value *= 10;
+ power -= 1;
+ }
+ return value;
+}
+
+
+static struct DirtyRateInfo *
+query_dirty_rate_info(TimeUnit calc_time_unit)
{
int i;
int64_t dirty_rate = DirtyStat.dirty_rate;
@@ -225,7 +256,10 @@ static struct DirtyRateInfo *query_dirty_rate_info(void)
info->status = CalculatingState;
info->start_time = DirtyStat.start_time;
- info->calc_time = DirtyStat.calc_time;
+ info->calc_time = convert_time_unit(DirtyStat.calc_time_ms,
+ TIME_UNIT_MILLISECOND,
+ calc_time_unit);
+ info->calc_time_unit = calc_time_unit;
info->sample_pages = DirtyStat.sample_pages;
info->mode = dirtyrate_mode;
@@ -259,12 +293,11 @@ static struct DirtyRateInfo *query_dirty_rate_info(void)
return info;
}
-static void init_dirtyrate_stat(int64_t start_time,
- struct DirtyRateConfig config)
+static void init_dirtyrate_stat(struct DirtyRateConfig config)
{
DirtyStat.dirty_rate = -1;
- DirtyStat.start_time = start_time;
- DirtyStat.calc_time = config.sample_period_seconds;
+ DirtyStat.start_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000;
+ DirtyStat.calc_time_ms = config.calc_time_ms;
DirtyStat.sample_pages = config.sample_pages_per_gigabytes;
switch (config.mode) {
@@ -574,7 +607,6 @@ static inline void dirtyrate_manual_reset_protect(void)
static void calculate_dirtyrate_dirty_bitmap(struct DirtyRateConfig config)
{
- int64_t msec = 0;
int64_t start_time;
DirtyPageRecord dirty_pages;
@@ -600,11 +632,9 @@ static void calculate_dirtyrate_dirty_bitmap(struct DirtyRateConfig config)
record_dirtypages_bitmap(&dirty_pages, true);
start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
- DirtyStat.start_time = start_time / 1000;
+ DirtyStat.start_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000;
- msec = config.sample_period_seconds * 1000;
- msec = dirty_stat_wait(msec, start_time);
- DirtyStat.calc_time = msec / 1000;
+ DirtyStat.calc_time_ms = dirty_stat_wait(config.calc_time_ms, start_time);
/*
* do two things.
@@ -615,12 +645,12 @@ static void calculate_dirtyrate_dirty_bitmap(struct DirtyRateConfig config)
record_dirtypages_bitmap(&dirty_pages, false);
- DirtyStat.dirty_rate = do_calculate_dirtyrate(dirty_pages, msec);
+ DirtyStat.dirty_rate = do_calculate_dirtyrate(dirty_pages,
+ DirtyStat.calc_time_ms);
}
static void calculate_dirtyrate_dirty_ring(struct DirtyRateConfig config)
{
- int64_t duration;
uint64_t dirtyrate = 0;
uint64_t dirtyrate_sum = 0;
int i = 0;
@@ -628,15 +658,13 @@ static void calculate_dirtyrate_dirty_ring(struct DirtyRateConfig config)
/* start log sync */
global_dirty_log_change(GLOBAL_DIRTY_DIRTY_RATE, true);
- DirtyStat.start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000;
+ DirtyStat.start_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000;
/* calculate vcpu dirtyrate */
- duration = vcpu_calculate_dirtyrate(config.sample_period_seconds * 1000,
- &DirtyStat.dirty_ring,
- GLOBAL_DIRTY_DIRTY_RATE,
- true);
-
- DirtyStat.calc_time = duration / 1000;
+ DirtyStat.calc_time_ms = vcpu_calculate_dirtyrate(config.calc_time_ms,
+ &DirtyStat.dirty_ring,
+ GLOBAL_DIRTY_DIRTY_RATE,
+ true);
/* calculate vm dirtyrate */
for (i = 0; i < DirtyStat.dirty_ring.nvcpu; i++) {
@@ -652,27 +680,25 @@ static void calculate_dirtyrate_sample_vm(struct DirtyRateConfig config)
{
struct RamblockDirtyInfo *block_dinfo = NULL;
int block_count = 0;
- int64_t msec = 0;
int64_t initial_time;
rcu_read_lock();
initial_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
+ DirtyStat.start_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000;
if (!record_ramblock_hash_info(&block_dinfo, config, &block_count)) {
goto out;
}
rcu_read_unlock();
- msec = config.sample_period_seconds * 1000;
- msec = dirty_stat_wait(msec, initial_time);
- DirtyStat.start_time = initial_time / 1000;
- DirtyStat.calc_time = msec / 1000;
+ DirtyStat.calc_time_ms = dirty_stat_wait(config.calc_time_ms,
+ initial_time);
rcu_read_lock();
if (!compare_page_hash_info(block_dinfo, block_count)) {
goto out;
}
- update_dirtyrate(msec);
+ update_dirtyrate(DirtyStat.calc_time_ms);
out:
rcu_read_unlock();
@@ -718,6 +744,8 @@ void *get_dirtyrate_thread(void *arg)
}
void qmp_calc_dirty_rate(int64_t calc_time,
+ bool has_calc_time_unit,
+ TimeUnit calc_time_unit,
bool has_sample_pages,
int64_t sample_pages,
bool has_mode,
@@ -727,7 +755,6 @@ void qmp_calc_dirty_rate(int64_t calc_time,
static struct DirtyRateConfig config;
QemuThread thread;
int ret;
- int64_t start_time;
/*
* If the dirty rate is already being measured, don't attempt to start.
@@ -737,10 +764,15 @@ void qmp_calc_dirty_rate(int64_t calc_time,
return;
}
- if (!is_sample_period_valid(calc_time)) {
- error_setg(errp, "calc-time is out of range[%d, %d].",
- MIN_FETCH_DIRTYRATE_TIME_SEC,
- MAX_FETCH_DIRTYRATE_TIME_SEC);
+ int64_t calc_time_ms = convert_time_unit(
+ calc_time,
+ has_calc_time_unit ? calc_time_unit : TIME_UNIT_SECOND,
+ TIME_UNIT_MILLISECOND
+ );
+
+ if (!is_calc_time_valid(calc_time_ms)) {
+ error_setg(errp, "Calculation time is out of range [%dms, %dms].",
+ MIN_CALC_TIME_MS, MAX_CALC_TIME_MS);
return;
}
@@ -787,7 +819,7 @@ void qmp_calc_dirty_rate(int64_t calc_time,
return;
}
- config.sample_period_seconds = calc_time;
+ config.calc_time_ms = calc_time_ms;
config.sample_pages_per_gigabytes = sample_pages;
config.mode = mode;
@@ -799,21 +831,24 @@ void qmp_calc_dirty_rate(int64_t calc_time,
**/
dirtyrate_mode = mode;
- start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000;
- init_dirtyrate_stat(start_time, config);
+ init_dirtyrate_stat(config);
qemu_thread_create(&thread, "get_dirtyrate", get_dirtyrate_thread,
(void *)&config, QEMU_THREAD_DETACHED);
}
-struct DirtyRateInfo *qmp_query_dirty_rate(Error **errp)
+
+struct DirtyRateInfo *qmp_query_dirty_rate(bool has_calc_time_unit,
+ TimeUnit calc_time_unit,
+ Error **errp)
{
- return query_dirty_rate_info();
+ return query_dirty_rate_info(
+ has_calc_time_unit ? calc_time_unit : TIME_UNIT_SECOND);
}
void hmp_info_dirty_rate(Monitor *mon, const QDict *qdict)
{
- DirtyRateInfo *info = query_dirty_rate_info();
+ DirtyRateInfo *info = query_dirty_rate_info(TIME_UNIT_SECOND);
monitor_printf(mon, "Status: %s\n",
DirtyRateStatus_str(info->status));
@@ -873,8 +908,11 @@ void hmp_calc_dirty_rate(Monitor *mon, const QDict *qdict)
mode = DIRTY_RATE_MEASURE_MODE_DIRTY_RING;
}
- qmp_calc_dirty_rate(sec, has_sample_pages, sample_pages, true,
- mode, &err);
+ qmp_calc_dirty_rate(sec, /* calc-time */
+ false, TIME_UNIT_SECOND, /* calc-time-unit */
+ has_sample_pages, sample_pages,
+ true, mode,
+ &err);
if (err) {
hmp_handle_error(mon, err);
return;
diff --git a/migration/dirtyrate.h b/migration/dirtyrate.h
index 594a5c0..869c060 100644
--- a/migration/dirtyrate.h
+++ b/migration/dirtyrate.h
@@ -31,10 +31,12 @@
#define MIN_RAMBLOCK_SIZE 128
/*
- * Take 1s as minimum time for calculation duration
+ * Allowed range for dirty page rate calculation (in milliseconds).
+ * Lower limit relates to the smallest realistic downtime it
+ * makes sense to impose on migration.
*/
-#define MIN_FETCH_DIRTYRATE_TIME_SEC 1
-#define MAX_FETCH_DIRTYRATE_TIME_SEC 60
+#define MIN_CALC_TIME_MS 50
+#define MAX_CALC_TIME_MS 60000
/*
* Take 1/16 pages in 1G as the maxmum sample page count
@@ -44,7 +46,7 @@
struct DirtyRateConfig {
uint64_t sample_pages_per_gigabytes; /* sample pages per GB */
- int64_t sample_period_seconds; /* time duration between two sampling */
+ int64_t calc_time_ms; /* desired calculation time (in milliseconds) */
DirtyRateMeasureMode mode; /* mode of dirtyrate measurement */
};
@@ -73,7 +75,7 @@ typedef struct SampleVMStat {
struct DirtyRateStat {
int64_t dirty_rate; /* dirty rate in MB/s */
int64_t start_time; /* calculation start time in units of second */
- int64_t calc_time; /* time duration of two sampling in units of second */
+ int64_t calc_time_ms; /* actual calculation time (in milliseconds) */
uint64_t sample_pages; /* sample pages per GB */
union {
SampleVMStat page_sampling;
diff --git a/nbd/client-connection.c b/nbd/client-connection.c
index aa0201b..f9da67c 100644
--- a/nbd/client-connection.c
+++ b/nbd/client-connection.c
@@ -93,7 +93,7 @@ NBDClientConnection *nbd_client_connection_new(const SocketAddress *saddr,
.do_negotiation = do_negotiation,
.initial_info.request_sizes = true,
- .initial_info.mode = NBD_MODE_STRUCTURED,
+ .initial_info.mode = NBD_MODE_EXTENDED,
.initial_info.base_allocation = true,
.initial_info.x_dirty_bitmap = g_strdup(x_dirty_bitmap),
.initial_info.name = g_strdup(export_name ?: "")
diff --git a/nbd/client.c b/nbd/client.c
index cecb0f0..29ffc60 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -953,15 +953,23 @@ static int nbd_start_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
if (fixedNewStyle) {
int result = 0;
+ if (max_mode >= NBD_MODE_EXTENDED) {
+ result = nbd_request_simple_option(ioc,
+ NBD_OPT_EXTENDED_HEADERS,
+ false, errp);
+ if (result) {
+ return result < 0 ? -EINVAL : NBD_MODE_EXTENDED;
+ }
+ }
if (max_mode >= NBD_MODE_STRUCTURED) {
result = nbd_request_simple_option(ioc,
NBD_OPT_STRUCTURED_REPLY,
false, errp);
- if (result < 0) {
- return -EINVAL;
+ if (result) {
+ return result < 0 ? -EINVAL : NBD_MODE_STRUCTURED;
}
}
- return result ? NBD_MODE_STRUCTURED : NBD_MODE_SIMPLE;
+ return NBD_MODE_SIMPLE;
} else {
return NBD_MODE_EXPORT_NAME;
}
@@ -1034,6 +1042,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
}
switch (info->mode) {
+ case NBD_MODE_EXTENDED:
case NBD_MODE_STRUCTURED:
if (base_allocation) {
result = nbd_negotiate_simple_meta_context(ioc, info, errp);
@@ -1144,7 +1153,7 @@ int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
*info = NULL;
result = nbd_start_negotiate(ioc, tlscreds, hostname, &sioc,
- NBD_MODE_STRUCTURED, NULL, errp);
+ NBD_MODE_EXTENDED, NULL, errp);
if (tlscreds && sioc) {
ioc = sioc;
}
@@ -1155,6 +1164,7 @@ int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
switch ((NBDMode)result) {
case NBD_MODE_SIMPLE:
case NBD_MODE_STRUCTURED:
+ case NBD_MODE_EXTENDED:
/* newstyle - use NBD_OPT_LIST to populate array, then try
* NBD_OPT_INFO on each array member. If structured replies
* are enabled, also try NBD_OPT_LIST_META_CONTEXT. */
@@ -1191,7 +1201,7 @@ int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
break;
}
- if (result == NBD_MODE_STRUCTURED &&
+ if (result >= NBD_MODE_STRUCTURED &&
nbd_list_meta_contexts(ioc, &array[i], errp) < 0) {
goto out;
}
@@ -1346,22 +1356,29 @@ int nbd_disconnect(int fd)
int nbd_send_request(QIOChannel *ioc, NBDRequest *request)
{
- uint8_t buf[NBD_REQUEST_SIZE];
+ uint8_t buf[NBD_EXTENDED_REQUEST_SIZE];
+ size_t len;
- assert(request->mode <= NBD_MODE_STRUCTURED); /* TODO handle extended */
- assert(request->len <= UINT32_MAX);
trace_nbd_send_request(request->from, request->len, request->cookie,
request->flags, request->type,
nbd_cmd_lookup(request->type));
- stl_be_p(buf, NBD_REQUEST_MAGIC);
stw_be_p(buf + 4, request->flags);
stw_be_p(buf + 6, request->type);
stq_be_p(buf + 8, request->cookie);
stq_be_p(buf + 16, request->from);
- stl_be_p(buf + 24, request->len);
+ if (request->mode >= NBD_MODE_EXTENDED) {
+ stl_be_p(buf, NBD_EXTENDED_REQUEST_MAGIC);
+ stq_be_p(buf + 24, request->len);
+ len = NBD_EXTENDED_REQUEST_SIZE;
+ } else {
+ assert(request->len <= UINT32_MAX);
+ stl_be_p(buf, NBD_REQUEST_MAGIC);
+ stl_be_p(buf + 24, request->len);
+ len = NBD_REQUEST_SIZE;
+ }
- return nbd_write(ioc, buf, sizeof(buf), NULL);
+ return nbd_write(ioc, buf, len, NULL);
}
/* nbd_receive_simple_reply
@@ -1388,30 +1405,36 @@ static int nbd_receive_simple_reply(QIOChannel *ioc, NBDSimpleReply *reply,
return 0;
}
-/* nbd_receive_structured_reply_chunk
+/* nbd_receive_reply_chunk_header
* Read structured reply chunk except magic field (which should be already
- * read).
+ * read). Normalize into the compact form.
* Payload is not read.
*/
-static int nbd_receive_structured_reply_chunk(QIOChannel *ioc,
- NBDStructuredReplyChunk *chunk,
- Error **errp)
+static int nbd_receive_reply_chunk_header(QIOChannel *ioc, NBDReply *chunk,
+ Error **errp)
{
int ret;
+ size_t len;
+ uint64_t payload_len;
- assert(chunk->magic == NBD_STRUCTURED_REPLY_MAGIC);
+ if (chunk->magic == NBD_STRUCTURED_REPLY_MAGIC) {
+ len = sizeof(chunk->structured);
+ } else {
+ assert(chunk->magic == NBD_EXTENDED_REPLY_MAGIC);
+ len = sizeof(chunk->extended);
+ }
ret = nbd_read(ioc, (uint8_t *)chunk + sizeof(chunk->magic),
- sizeof(*chunk) - sizeof(chunk->magic), "structured chunk",
+ len - sizeof(chunk->magic), "structured chunk",
errp);
if (ret < 0) {
return ret;
}
- chunk->flags = be16_to_cpu(chunk->flags);
- chunk->type = be16_to_cpu(chunk->type);
- chunk->cookie = be64_to_cpu(chunk->cookie);
- chunk->length = be32_to_cpu(chunk->length);
+ /* flags, type, and cookie occupy same space between forms */
+ chunk->structured.flags = be16_to_cpu(chunk->structured.flags);
+ chunk->structured.type = be16_to_cpu(chunk->structured.type);
+ chunk->structured.cookie = be64_to_cpu(chunk->structured.cookie);
/*
* Because we use BLOCK_STATUS with REQ_ONE, and cap READ requests
@@ -1419,11 +1442,20 @@ static int nbd_receive_structured_reply_chunk(QIOChannel *ioc,
* this. Even if we stopped using REQ_ONE, sane servers will cap
* the number of extents they return for block status.
*/
- if (chunk->length > NBD_MAX_BUFFER_SIZE + sizeof(NBDStructuredReadData)) {
+ if (chunk->magic == NBD_STRUCTURED_REPLY_MAGIC) {
+ payload_len = be32_to_cpu(chunk->structured.length);
+ } else {
+ /* For now, we are ignoring the extended header offset. */
+ payload_len = be64_to_cpu(chunk->extended.length);
+ chunk->magic = NBD_STRUCTURED_REPLY_MAGIC;
+ }
+ if (payload_len > NBD_MAX_BUFFER_SIZE + sizeof(NBDStructuredReadData)) {
error_setg(errp, "server chunk %" PRIu32 " (%s) payload is too long",
- chunk->type, nbd_rep_lookup(chunk->type));
+ chunk->structured.type,
+ nbd_rep_lookup(chunk->structured.type));
return -EINVAL;
}
+ chunk->structured.length = payload_len;
return 0;
}
@@ -1470,19 +1502,21 @@ nbd_read_eof(BlockDriverState *bs, QIOChannel *ioc, void *buffer, size_t size,
/* nbd_receive_reply
*
- * Decreases bs->in_flight while waiting for a new reply. This yield is where
- * we wait indefinitely and the coroutine must be able to be safely reentered
- * for nbd_client_attach_aio_context().
+ * Wait for a new reply. If this yields, the coroutine must be able to be
+ * safely reentered for nbd_client_attach_aio_context(). @mode determines
+ * which reply magic we are expecting, although this normalizes the result
+ * so that the caller only has to work with compact headers.
*
* Returns 1 on success
- * 0 on eof, when no data was read (errp is not set)
- * negative errno on failure (errp is set)
+ * 0 on eof, when no data was read
+ * negative errno on failure
*/
int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
- NBDReply *reply, Error **errp)
+ NBDReply *reply, NBDMode mode, Error **errp)
{
int ret;
const char *type;
+ uint32_t expected;
ret = nbd_read_eof(bs, ioc, &reply->magic, sizeof(reply->magic), errp);
if (ret <= 0) {
@@ -1491,34 +1525,44 @@ int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
reply->magic = be32_to_cpu(reply->magic);
+ /* Diagnose but accept wrong-width header */
switch (reply->magic) {
case NBD_SIMPLE_REPLY_MAGIC:
+ if (mode >= NBD_MODE_EXTENDED) {
+ trace_nbd_receive_wrong_header(reply->magic,
+ nbd_mode_lookup(mode));
+ }
ret = nbd_receive_simple_reply(ioc, &reply->simple, errp);
if (ret < 0) {
- break;
+ return ret;
}
trace_nbd_receive_simple_reply(reply->simple.error,
nbd_err_lookup(reply->simple.error),
reply->cookie);
break;
case NBD_STRUCTURED_REPLY_MAGIC:
- ret = nbd_receive_structured_reply_chunk(ioc, &reply->structured, errp);
+ case NBD_EXTENDED_REPLY_MAGIC:
+ expected = mode >= NBD_MODE_EXTENDED ? NBD_EXTENDED_REPLY_MAGIC
+ : NBD_STRUCTURED_REPLY_MAGIC;
+ if (reply->magic != expected) {
+ trace_nbd_receive_wrong_header(reply->magic,
+ nbd_mode_lookup(mode));
+ }
+ ret = nbd_receive_reply_chunk_header(ioc, reply, errp);
if (ret < 0) {
- break;
+ return ret;
}
type = nbd_reply_type_lookup(reply->structured.type);
- trace_nbd_receive_structured_reply_chunk(reply->structured.flags,
- reply->structured.type, type,
- reply->structured.cookie,
- reply->structured.length);
+ trace_nbd_receive_reply_chunk_header(reply->structured.flags,
+ reply->structured.type, type,
+ reply->structured.cookie,
+ reply->structured.length);
break;
default:
+ trace_nbd_receive_wrong_header(reply->magic, nbd_mode_lookup(mode));
error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", reply->magic);
return -EINVAL;
}
- if (ret < 0) {
- return ret;
- }
return 1;
}
diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
index 133b1d9..dfa02f7 100644
--- a/nbd/nbd-internal.h
+++ b/nbd/nbd-internal.h
@@ -34,8 +34,11 @@
* https://github.com/yoe/nbd/blob/master/doc/proto.md
*/
-/* Size of all NBD_OPT_*, without payload */
+/* Size of all compact NBD_CMD_*, without payload */
#define NBD_REQUEST_SIZE (4 + 2 + 2 + 8 + 8 + 4)
+/* Size of all extended NBD_CMD_*, without payload */
+#define NBD_EXTENDED_REQUEST_SIZE (4 + 2 + 2 + 8 + 8 + 8)
+
/* Size of all NBD_REP_* sent in answer to most NBD_OPT_*, without payload */
#define NBD_REPLY_SIZE (4 + 4 + 8)
/* Size of reply to NBD_OPT_EXPORT_NAME */
diff --git a/nbd/server.c b/nbd/server.c
index 7a6f950..859c163 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -105,11 +105,13 @@ struct NBDExport {
static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
-/* NBDExportMetaContexts represents a list of contexts to be exported,
+/*
+ * NBDMetaContexts represents a list of meta contexts in use,
* as selected by NBD_OPT_SET_META_CONTEXT. Also used for
- * NBD_OPT_LIST_META_CONTEXT. */
-typedef struct NBDExportMetaContexts {
- NBDExport *exp;
+ * NBD_OPT_LIST_META_CONTEXT.
+ */
+struct NBDMetaContexts {
+ const NBDExport *exp; /* associated export */
size_t count; /* number of negotiated contexts */
bool base_allocation; /* export base:allocation context (block status) */
bool allocation_depth; /* export qemu:allocation-depth */
@@ -117,7 +119,7 @@ typedef struct NBDExportMetaContexts {
* export qemu:dirty-bitmap:<export bitmap name>,
* sized by exp->nr_export_bitmaps
*/
-} NBDExportMetaContexts;
+};
struct NBDClient {
int refcount;
@@ -144,7 +146,7 @@ struct NBDClient {
uint32_t check_align; /* If non-zero, check for aligned client requests */
NBDMode mode;
- NBDExportMetaContexts export_meta;
+ NBDMetaContexts contexts; /* Negotiated meta contexts */
uint32_t opt; /* Current option being negotiated */
uint32_t optlen; /* remaining length of data in ioc for the option being
@@ -455,10 +457,10 @@ static int nbd_negotiate_handle_list(NBDClient *client, Error **errp)
return nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
}
-static void nbd_check_meta_export(NBDClient *client)
+static void nbd_check_meta_export(NBDClient *client, NBDExport *exp)
{
- if (client->exp != client->export_meta.exp) {
- client->export_meta.count = 0;
+ if (exp != client->contexts.exp) {
+ client->contexts.count = 0;
}
}
@@ -482,6 +484,10 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, bool no_zeroes,
[10 .. 133] reserved (0) [unless no_zeroes]
*/
trace_nbd_negotiate_handle_export_name();
+ if (client->mode >= NBD_MODE_EXTENDED) {
+ error_setg(errp, "Extended headers already negotiated");
+ return -EINVAL;
+ }
if (client->optlen > NBD_MAX_STRING_SIZE) {
error_setg(errp, "Bad length received");
return -EINVAL;
@@ -500,11 +506,15 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, bool no_zeroes,
error_setg(errp, "export not found");
return -EINVAL;
}
+ nbd_check_meta_export(client, client->exp);
myflags = client->exp->nbdflags;
if (client->mode >= NBD_MODE_STRUCTURED) {
myflags |= NBD_FLAG_SEND_DF;
}
+ if (client->mode >= NBD_MODE_EXTENDED && client->contexts.count) {
+ myflags |= NBD_FLAG_BLOCK_STAT_PAYLOAD;
+ }
trace_nbd_negotiate_new_style_size_flags(client->exp->size, myflags);
stq_be_p(buf, client->exp->size);
stw_be_p(buf + 8, myflags);
@@ -517,7 +527,6 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, bool no_zeroes,
QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
blk_exp_ref(&client->exp->common);
- nbd_check_meta_export(client);
return 0;
}
@@ -637,6 +646,9 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp)
errp, "export '%s' not present",
sane_name);
}
+ if (client->opt == NBD_OPT_GO) {
+ nbd_check_meta_export(client, exp);
+ }
/* Don't bother sending NBD_INFO_NAME unless client requested it */
if (sendname) {
@@ -690,6 +702,10 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp)
if (client->mode >= NBD_MODE_STRUCTURED) {
myflags |= NBD_FLAG_SEND_DF;
}
+ if (client->mode >= NBD_MODE_EXTENDED &&
+ (client->contexts.count || client->opt == NBD_OPT_INFO)) {
+ myflags |= NBD_FLAG_BLOCK_STAT_PAYLOAD;
+ }
trace_nbd_negotiate_new_style_size_flags(exp->size, myflags);
stq_be_p(buf, exp->size);
stw_be_p(buf + 8, myflags);
@@ -725,7 +741,6 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp)
client->check_align = check_align;
QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
blk_exp_ref(&client->exp->common);
- nbd_check_meta_export(client);
rc = 1;
}
return rc;
@@ -848,7 +863,7 @@ static bool nbd_strshift(const char **str, const char *prefix)
* Handle queries to 'base' namespace. For now, only the base:allocation
* context is available. Return true if @query has been handled.
*/
-static bool nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *meta,
+static bool nbd_meta_base_query(NBDClient *client, NBDMetaContexts *meta,
const char *query)
{
if (!nbd_strshift(&query, "base:")) {
@@ -868,7 +883,7 @@ static bool nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *meta,
* and qemu:allocation-depth contexts are available. Return true if @query
* has been handled.
*/
-static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta,
+static bool nbd_meta_qemu_query(NBDClient *client, NBDMetaContexts *meta,
const char *query)
{
size_t i;
@@ -934,7 +949,7 @@ static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta,
* Return -errno on I/O error, 0 if option was completely handled by
* sending a reply about inconsistent lengths, or 1 on success. */
static int nbd_negotiate_meta_query(NBDClient *client,
- NBDExportMetaContexts *meta, Error **errp)
+ NBDMetaContexts *meta, Error **errp)
{
int ret;
g_autofree char *query = NULL;
@@ -973,14 +988,14 @@ static int nbd_negotiate_meta_query(NBDClient *client,
* Handle NBD_OPT_LIST_META_CONTEXT and NBD_OPT_SET_META_CONTEXT
*
* Return -errno on I/O error, or 0 if option was completely handled. */
-static int nbd_negotiate_meta_queries(NBDClient *client,
- NBDExportMetaContexts *meta, Error **errp)
+static int nbd_negotiate_meta_queries(NBDClient *client, Error **errp)
{
int ret;
g_autofree char *export_name = NULL;
/* Mark unused to work around https://bugs.llvm.org/show_bug.cgi?id=3888 */
g_autofree G_GNUC_UNUSED bool *bitmaps = NULL;
- NBDExportMetaContexts local_meta = {0};
+ NBDMetaContexts local_meta = {0};
+ NBDMetaContexts *meta;
uint32_t nb_queries;
size_t i;
size_t count = 0;
@@ -996,6 +1011,8 @@ static int nbd_negotiate_meta_queries(NBDClient *client,
if (client->opt == NBD_OPT_LIST_META_CONTEXT) {
/* Only change the caller's meta on SET. */
meta = &local_meta;
+ } else {
+ meta = &client->contexts;
}
g_free(meta->bitmaps);
@@ -1264,6 +1281,10 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
case NBD_OPT_STRUCTURED_REPLY:
if (length) {
ret = nbd_reject_length(client, false, errp);
+ } else if (client->mode >= NBD_MODE_EXTENDED) {
+ ret = nbd_negotiate_send_rep_err(
+ client, NBD_REP_ERR_EXT_HEADER_REQD, errp,
+ "extended headers already negotiated");
} else if (client->mode >= NBD_MODE_STRUCTURED) {
ret = nbd_negotiate_send_rep_err(
client, NBD_REP_ERR_INVALID, errp,
@@ -1276,8 +1297,20 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
case NBD_OPT_LIST_META_CONTEXT:
case NBD_OPT_SET_META_CONTEXT:
- ret = nbd_negotiate_meta_queries(client, &client->export_meta,
- errp);
+ ret = nbd_negotiate_meta_queries(client, errp);
+ break;
+
+ case NBD_OPT_EXTENDED_HEADERS:
+ if (length) {
+ ret = nbd_reject_length(client, false, errp);
+ } else if (client->mode >= NBD_MODE_EXTENDED) {
+ ret = nbd_negotiate_send_rep_err(
+ client, NBD_REP_ERR_INVALID, errp,
+ "extended headers already negotiated");
+ } else {
+ ret = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
+ client->mode = NBD_MODE_EXTENDED;
+ }
break;
default:
@@ -1411,11 +1444,13 @@ nbd_read_eof(NBDClient *client, void *buffer, size_t size, Error **errp)
static int coroutine_fn nbd_receive_request(NBDClient *client, NBDRequest *request,
Error **errp)
{
- uint8_t buf[NBD_REQUEST_SIZE];
- uint32_t magic;
+ uint8_t buf[NBD_EXTENDED_REQUEST_SIZE];
+ uint32_t magic, expect;
int ret;
+ size_t size = client->mode >= NBD_MODE_EXTENDED ?
+ NBD_EXTENDED_REQUEST_SIZE : NBD_REQUEST_SIZE;
- ret = nbd_read_eof(client, buf, sizeof(buf), errp);
+ ret = nbd_read_eof(client, buf, size, errp);
if (ret < 0) {
return ret;
}
@@ -1423,13 +1458,21 @@ static int coroutine_fn nbd_receive_request(NBDClient *client, NBDRequest *reque
return -EIO;
}
- /* Request
- [ 0 .. 3] magic (NBD_REQUEST_MAGIC)
- [ 4 .. 5] flags (NBD_CMD_FLAG_FUA, ...)
- [ 6 .. 7] type (NBD_CMD_READ, ...)
- [ 8 .. 15] cookie
- [16 .. 23] from
- [24 .. 27] len
+ /*
+ * Compact request
+ * [ 0 .. 3] magic (NBD_REQUEST_MAGIC)
+ * [ 4 .. 5] flags (NBD_CMD_FLAG_FUA, ...)
+ * [ 6 .. 7] type (NBD_CMD_READ, ...)
+ * [ 8 .. 15] cookie
+ * [16 .. 23] from
+ * [24 .. 27] len
+ * Extended request
+ * [ 0 .. 3] magic (NBD_EXTENDED_REQUEST_MAGIC)
+ * [ 4 .. 5] flags (NBD_CMD_FLAG_FUA, NBD_CMD_FLAG_PAYLOAD_LEN, ...)
+ * [ 6 .. 7] type (NBD_CMD_READ, ...)
+ * [ 8 .. 15] cookie
+ * [16 .. 23] from
+ * [24 .. 31] len
*/
magic = ldl_be_p(buf);
@@ -1437,13 +1480,20 @@ static int coroutine_fn nbd_receive_request(NBDClient *client, NBDRequest *reque
request->type = lduw_be_p(buf + 6);
request->cookie = ldq_be_p(buf + 8);
request->from = ldq_be_p(buf + 16);
- request->len = (uint32_t)ldl_be_p(buf + 24); /* widen 32 to 64 bits */
+ if (client->mode >= NBD_MODE_EXTENDED) {
+ request->len = ldq_be_p(buf + 24);
+ expect = NBD_EXTENDED_REQUEST_MAGIC;
+ } else {
+ request->len = (uint32_t)ldl_be_p(buf + 24); /* widen 32 to 64 bits */
+ expect = NBD_REQUEST_MAGIC;
+ }
trace_nbd_receive_request(magic, request->flags, request->type,
request->from, request->len);
- if (magic != NBD_REQUEST_MAGIC) {
- error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", magic);
+ if (magic != expect) {
+ error_setg(errp, "invalid magic (got 0x%" PRIx32 ", expected 0x%"
+ PRIx32 ")", magic, expect);
return -EINVAL;
}
return 0;
@@ -1474,7 +1524,7 @@ void nbd_client_put(NBDClient *client)
QTAILQ_REMOVE(&client->exp->clients, client, next);
blk_exp_unref(&client->exp->common);
}
- g_free(client->export_meta.bitmaps);
+ g_free(client->contexts.bitmaps);
g_free(client);
}
}
@@ -1921,8 +1971,6 @@ static inline void set_be_chunk(NBDClient *client, struct iovec *iov,
size_t niov, uint16_t flags, uint16_t type,
NBDRequest *request)
{
- /* TODO - handle structured vs. extended replies */
- NBDStructuredReplyChunk *chunk = iov->iov_base;
size_t i, length = 0;
for (i = 1; i < niov; i++) {
@@ -1930,12 +1978,26 @@ static inline void set_be_chunk(NBDClient *client, struct iovec *iov,
}
assert(length <= NBD_MAX_BUFFER_SIZE + sizeof(NBDStructuredReadData));
- iov[0].iov_len = sizeof(*chunk);
- stl_be_p(&chunk->magic, NBD_STRUCTURED_REPLY_MAGIC);
- stw_be_p(&chunk->flags, flags);
- stw_be_p(&chunk->type, type);
- stq_be_p(&chunk->cookie, request->cookie);
- stl_be_p(&chunk->length, length);
+ if (client->mode >= NBD_MODE_EXTENDED) {
+ NBDExtendedReplyChunk *chunk = iov->iov_base;
+
+ iov[0].iov_len = sizeof(*chunk);
+ stl_be_p(&chunk->magic, NBD_EXTENDED_REPLY_MAGIC);
+ stw_be_p(&chunk->flags, flags);
+ stw_be_p(&chunk->type, type);
+ stq_be_p(&chunk->cookie, request->cookie);
+ stq_be_p(&chunk->offset, request->from);
+ stq_be_p(&chunk->length, length);
+ } else {
+ NBDStructuredReplyChunk *chunk = iov->iov_base;
+
+ iov[0].iov_len = sizeof(*chunk);
+ stl_be_p(&chunk->magic, NBD_STRUCTURED_REPLY_MAGIC);
+ stw_be_p(&chunk->flags, flags);
+ stw_be_p(&chunk->type, type);
+ stq_be_p(&chunk->cookie, request->cookie);
+ stl_be_p(&chunk->length, length);
+ }
}
static int coroutine_fn nbd_co_send_chunk_done(NBDClient *client,
@@ -2074,20 +2136,24 @@ static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client,
}
typedef struct NBDExtentArray {
- NBDExtent32 *extents;
+ NBDExtent64 *extents;
unsigned int nb_alloc;
unsigned int count;
uint64_t total_length;
+ bool extended;
bool can_add;
bool converted_to_be;
} NBDExtentArray;
-static NBDExtentArray *nbd_extent_array_new(unsigned int nb_alloc)
+static NBDExtentArray *nbd_extent_array_new(unsigned int nb_alloc,
+ NBDMode mode)
{
NBDExtentArray *ea = g_new0(NBDExtentArray, 1);
+ assert(mode >= NBD_MODE_STRUCTURED);
ea->nb_alloc = nb_alloc;
- ea->extents = g_new(NBDExtent32, nb_alloc);
+ ea->extents = g_new(NBDExtent64, nb_alloc);
+ ea->extended = mode >= NBD_MODE_EXTENDED;
ea->can_add = true;
return ea;
@@ -2106,15 +2172,36 @@ static void nbd_extent_array_convert_to_be(NBDExtentArray *ea)
int i;
assert(!ea->converted_to_be);
+ assert(ea->extended);
ea->can_add = false;
ea->converted_to_be = true;
for (i = 0; i < ea->count; i++) {
- ea->extents[i].flags = cpu_to_be32(ea->extents[i].flags);
- ea->extents[i].length = cpu_to_be32(ea->extents[i].length);
+ ea->extents[i].length = cpu_to_be64(ea->extents[i].length);
+ ea->extents[i].flags = cpu_to_be64(ea->extents[i].flags);
}
}
+/* Further modifications of the array after conversion are abandoned */
+static NBDExtent32 *nbd_extent_array_convert_to_narrow(NBDExtentArray *ea)
+{
+ int i;
+ NBDExtent32 *extents = g_new(NBDExtent32, ea->count);
+
+ assert(!ea->converted_to_be);
+ assert(!ea->extended);
+ ea->can_add = false;
+ ea->converted_to_be = true;
+
+ for (i = 0; i < ea->count; i++) {
+ assert((ea->extents[i].length | ea->extents[i].flags) <= UINT32_MAX);
+ extents[i].length = cpu_to_be32(ea->extents[i].length);
+ extents[i].flags = cpu_to_be32(ea->extents[i].flags);
+ }
+
+ return extents;
+}
+
/*
* Add extent to NBDExtentArray. If extent can't be added (no available space),
* return -1.
@@ -2125,19 +2212,27 @@ static void nbd_extent_array_convert_to_be(NBDExtentArray *ea)
* would result in an incorrect range reported to the client)
*/
static int nbd_extent_array_add(NBDExtentArray *ea,
- uint32_t length, uint32_t flags)
+ uint64_t length, uint32_t flags)
{
assert(ea->can_add);
if (!length) {
return 0;
}
+ if (!ea->extended) {
+ assert(length <= UINT32_MAX);
+ }
/* Extend previous extent if flags are the same */
if (ea->count > 0 && flags == ea->extents[ea->count - 1].flags) {
- uint64_t sum = (uint64_t)length + ea->extents[ea->count - 1].length;
+ uint64_t sum = length + ea->extents[ea->count - 1].length;
- if (sum <= UINT32_MAX) {
+ /*
+ * sum cannot overflow: the block layer bounds image size at
+ * 2^63, and ea->extents[].length comes from the block layer.
+ */
+ assert(sum >= length);
+ if (sum <= UINT32_MAX || ea->extended) {
ea->extents[ea->count - 1].length = sum;
ea->total_length += length;
return 0;
@@ -2150,7 +2245,7 @@ static int nbd_extent_array_add(NBDExtentArray *ea,
}
ea->total_length += length;
- ea->extents[ea->count] = (NBDExtent32) {.length = length, .flags = flags};
+ ea->extents[ea->count] = (NBDExtent64) {.length = length, .flags = flags};
ea->count++;
return 0;
@@ -2219,20 +2314,39 @@ nbd_co_send_extents(NBDClient *client, NBDRequest *request, NBDExtentArray *ea,
bool last, uint32_t context_id, Error **errp)
{
NBDReply hdr;
- NBDStructuredMeta chunk;
- struct iovec iov[] = {
- {.iov_base = &hdr},
- {.iov_base = &chunk, .iov_len = sizeof(chunk)},
- {.iov_base = ea->extents, .iov_len = ea->count * sizeof(ea->extents[0])}
- };
+ NBDStructuredMeta meta;
+ NBDExtendedMeta meta_ext;
+ g_autofree NBDExtent32 *extents = NULL;
+ uint16_t type;
+ struct iovec iov[] = { {.iov_base = &hdr}, {0}, {0} };
+
+ if (client->mode >= NBD_MODE_EXTENDED) {
+ type = NBD_REPLY_TYPE_BLOCK_STATUS_EXT;
+
+ iov[1].iov_base = &meta_ext;
+ iov[1].iov_len = sizeof(meta_ext);
+ stl_be_p(&meta_ext.context_id, context_id);
+ stl_be_p(&meta_ext.count, ea->count);
+
+ nbd_extent_array_convert_to_be(ea);
+ iov[2].iov_base = ea->extents;
+ iov[2].iov_len = ea->count * sizeof(ea->extents[0]);
+ } else {
+ type = NBD_REPLY_TYPE_BLOCK_STATUS;
+
+ iov[1].iov_base = &meta;
+ iov[1].iov_len = sizeof(meta);
+ stl_be_p(&meta.context_id, context_id);
- nbd_extent_array_convert_to_be(ea);
+ extents = nbd_extent_array_convert_to_narrow(ea);
+ iov[2].iov_base = extents;
+ iov[2].iov_len = ea->count * sizeof(extents[0]);
+ }
trace_nbd_co_send_extents(request->cookie, ea->count, context_id,
ea->total_length, last);
- set_be_chunk(client, iov, 3, last ? NBD_REPLY_FLAG_DONE : 0,
- NBD_REPLY_TYPE_BLOCK_STATUS, request);
- stl_be_p(&chunk.context_id, context_id);
+ set_be_chunk(client, iov, 3, last ? NBD_REPLY_FLAG_DONE : 0, type,
+ request);
return nbd_co_send_iov(client, iov, 3, errp);
}
@@ -2241,13 +2355,14 @@ nbd_co_send_extents(NBDClient *client, NBDRequest *request, NBDExtentArray *ea,
static int
coroutine_fn nbd_co_send_block_status(NBDClient *client, NBDRequest *request,
BlockBackend *blk, uint64_t offset,
- uint32_t length, bool dont_fragment,
+ uint64_t length, bool dont_fragment,
bool last, uint32_t context_id,
Error **errp)
{
int ret;
unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BLOCK_STATUS_EXTENTS;
- g_autoptr(NBDExtentArray) ea = nbd_extent_array_new(nb_extents);
+ g_autoptr(NBDExtentArray) ea =
+ nbd_extent_array_new(nb_extents, client->mode);
if (context_id == NBD_META_ID_BASE_ALLOCATION) {
ret = blockstatus_to_extents(blk, offset, length, ea);
@@ -2270,11 +2385,12 @@ static void bitmap_to_extents(BdrvDirtyBitmap *bitmap,
int64_t start, dirty_start, dirty_count;
int64_t end = offset + length;
bool full = false;
+ int64_t bound = es->extended ? INT64_MAX : INT32_MAX;
bdrv_dirty_bitmap_lock(bitmap);
for (start = offset;
- bdrv_dirty_bitmap_next_dirty_area(bitmap, start, end, INT32_MAX,
+ bdrv_dirty_bitmap_next_dirty_area(bitmap, start, end, bound,
&dirty_start, &dirty_count);
start = dirty_start + dirty_count)
{
@@ -2298,18 +2414,103 @@ static int coroutine_fn nbd_co_send_bitmap(NBDClient *client,
NBDRequest *request,
BdrvDirtyBitmap *bitmap,
uint64_t offset,
- uint32_t length, bool dont_fragment,
+ uint64_t length, bool dont_fragment,
bool last, uint32_t context_id,
Error **errp)
{
unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BLOCK_STATUS_EXTENTS;
- g_autoptr(NBDExtentArray) ea = nbd_extent_array_new(nb_extents);
+ g_autoptr(NBDExtentArray) ea =
+ nbd_extent_array_new(nb_extents, client->mode);
bitmap_to_extents(bitmap, offset, length, ea);
return nbd_co_send_extents(client, request, ea, last, context_id, errp);
}
+/*
+ * nbd_co_block_status_payload_read
+ * Called when a client wants a subset of negotiated contexts via a
+ * BLOCK_STATUS payload. Check the payload for valid length and
+ * contents. On success, return 0 with request updated to effective
+ * length. If request was invalid but all payload consumed, return 0
+ * with request->len and request->contexts->count set to 0 (which will
+ * trigger an appropriate NBD_EINVAL response later on). Return
+ * negative errno if the payload was not fully consumed.
+ */
+static int
+nbd_co_block_status_payload_read(NBDClient *client, NBDRequest *request,
+ Error **errp)
+{
+ uint64_t payload_len = request->len;
+ g_autofree char *buf = NULL;
+ size_t count, i, nr_bitmaps;
+ uint32_t id;
+
+ if (payload_len > NBD_MAX_BUFFER_SIZE) {
+ error_setg(errp, "len (%" PRIu64 ") is larger than max len (%u)",
+ request->len, NBD_MAX_BUFFER_SIZE);
+ return -EINVAL;
+ }
+
+ assert(client->contexts.exp == client->exp);
+ nr_bitmaps = client->exp->nr_export_bitmaps;
+ request->contexts = g_new0(NBDMetaContexts, 1);
+ request->contexts->exp = client->exp;
+
+ if (payload_len % sizeof(uint32_t) ||
+ payload_len < sizeof(NBDBlockStatusPayload) ||
+ payload_len > (sizeof(NBDBlockStatusPayload) +
+ sizeof(id) * client->contexts.count)) {
+ goto skip;
+ }
+
+ buf = g_malloc(payload_len);
+ if (nbd_read(client->ioc, buf, payload_len,
+ "CMD_BLOCK_STATUS data", errp) < 0) {
+ return -EIO;
+ }
+ trace_nbd_co_receive_request_payload_received(request->cookie,
+ payload_len);
+ request->contexts->bitmaps = g_new0(bool, nr_bitmaps);
+ count = (payload_len - sizeof(NBDBlockStatusPayload)) / sizeof(id);
+ payload_len = 0;
+
+ for (i = 0; i < count; i++) {
+ id = ldl_be_p(buf + sizeof(NBDBlockStatusPayload) + sizeof(id) * i);
+ if (id == NBD_META_ID_BASE_ALLOCATION) {
+ if (!client->contexts.base_allocation ||
+ request->contexts->base_allocation) {
+ goto skip;
+ }
+ request->contexts->base_allocation = true;
+ } else if (id == NBD_META_ID_ALLOCATION_DEPTH) {
+ if (!client->contexts.allocation_depth ||
+ request->contexts->allocation_depth) {
+ goto skip;
+ }
+ request->contexts->allocation_depth = true;
+ } else {
+ unsigned idx = id - NBD_META_ID_DIRTY_BITMAP;
+
+ if (idx >= nr_bitmaps || !client->contexts.bitmaps[idx] ||
+ request->contexts->bitmaps[idx]) {
+ goto skip;
+ }
+ request->contexts->bitmaps[idx] = true;
+ }
+ }
+
+ request->len = ldq_be_p(buf);
+ request->contexts->count = count;
+ return 0;
+
+ skip:
+ trace_nbd_co_receive_block_status_payload_compliance(request->from,
+ request->len);
+ request->len = request->contexts->count = 0;
+ return nbd_drop(client->ioc, payload_len, errp);
+}
+
/* nbd_co_receive_request
* Collect a client request. Return 0 if request looks valid, -EIO to drop
* connection right away, -EAGAIN to indicate we were interrupted and the
@@ -2322,10 +2523,12 @@ static int coroutine_fn nbd_co_receive_request(NBDRequestData *req,
Error **errp)
{
NBDClient *client = req->client;
+ bool extended_with_payload;
bool check_length = false;
bool check_rofs = false;
bool allocate_buffer = false;
- unsigned payload_len = 0;
+ bool payload_okay = false;
+ uint64_t payload_len = 0;
int valid_flags = NBD_CMD_FLAG_FUA;
int ret;
@@ -2338,6 +2541,13 @@ static int coroutine_fn nbd_co_receive_request(NBDRequestData *req,
trace_nbd_co_receive_request_decode_type(request->cookie, request->type,
nbd_cmd_lookup(request->type));
+ extended_with_payload = client->mode >= NBD_MODE_EXTENDED &&
+ request->flags & NBD_CMD_FLAG_PAYLOAD_LEN;
+ if (extended_with_payload) {
+ payload_len = request->len;
+ check_length = true;
+ }
+
switch (request->type) {
case NBD_CMD_DISC:
/* Special case: we're going to disconnect without a reply,
@@ -2354,6 +2564,15 @@ static int coroutine_fn nbd_co_receive_request(NBDRequestData *req,
break;
case NBD_CMD_WRITE:
+ if (client->mode >= NBD_MODE_EXTENDED) {
+ if (!extended_with_payload) {
+ /* The client is noncompliant. Trace it, but proceed. */
+ trace_nbd_co_receive_ext_payload_compliance(request->from,
+ request->len);
+ }
+ valid_flags |= NBD_CMD_FLAG_PAYLOAD_LEN;
+ }
+ payload_okay = true;
payload_len = request->len;
check_length = true;
allocate_buffer = true;
@@ -2377,6 +2596,18 @@ static int coroutine_fn nbd_co_receive_request(NBDRequestData *req,
break;
case NBD_CMD_BLOCK_STATUS:
+ if (extended_with_payload) {
+ ret = nbd_co_block_status_payload_read(client, request, errp);
+ if (ret < 0) {
+ return ret;
+ }
+ /* payload now consumed */
+ check_length = false;
+ payload_len = 0;
+ valid_flags |= NBD_CMD_FLAG_PAYLOAD_LEN;
+ } else {
+ request->contexts = &client->contexts;
+ }
valid_flags |= NBD_CMD_FLAG_REQ_ONE;
break;
@@ -2395,6 +2626,16 @@ static int coroutine_fn nbd_co_receive_request(NBDRequestData *req,
request->len, NBD_MAX_BUFFER_SIZE);
return -EINVAL;
}
+ if (payload_len && !payload_okay) {
+ /*
+ * For now, we don't support payloads on other commands; but
+ * we can keep the connection alive by ignoring the payload.
+ * We will fail the command later with NBD_EINVAL for the use
+ * of an unsupported flag (and not for access beyond bounds).
+ */
+ assert(request->type != NBD_CMD_WRITE);
+ request->len = 0;
+ }
if (allocate_buffer) {
/* READ, WRITE */
req->data = blk_try_blockalign(client->exp->common.blk,
@@ -2405,10 +2646,14 @@ static int coroutine_fn nbd_co_receive_request(NBDRequestData *req,
}
}
if (payload_len) {
- /* WRITE */
- assert(req->data);
- ret = nbd_read(client->ioc, req->data, payload_len,
- "CMD_WRITE data", errp);
+ if (payload_okay) {
+ /* WRITE */
+ assert(req->data);
+ ret = nbd_read(client->ioc, req->data, payload_len,
+ "CMD_WRITE data", errp);
+ } else {
+ ret = nbd_drop(client->ioc, payload_len, errp);
+ }
if (ret < 0) {
return -EIO;
}
@@ -2463,6 +2708,8 @@ static coroutine_fn int nbd_send_generic_reply(NBDClient *client,
{
if (client->mode >= NBD_MODE_STRUCTURED && ret < 0) {
return nbd_co_send_chunk_error(client, request, -ret, error_msg, errp);
+ } else if (client->mode >= NBD_MODE_EXTENDED) {
+ return nbd_co_send_chunk_done(client, request, errp);
} else {
return nbd_co_send_simple_reply(client, request, ret < 0 ? -ret : 0,
NULL, 0, errp);
@@ -2604,16 +2851,18 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
"discard failed", errp);
case NBD_CMD_BLOCK_STATUS:
- if (!request->len) {
- return nbd_send_generic_reply(client, request, -EINVAL,
- "need non-zero length", errp);
- }
- assert(request->len <= UINT32_MAX);
- if (client->export_meta.count) {
+ assert(request->contexts);
+ assert(client->mode >= NBD_MODE_EXTENDED ||
+ request->len <= UINT32_MAX);
+ if (request->contexts->count) {
bool dont_fragment = request->flags & NBD_CMD_FLAG_REQ_ONE;
- int contexts_remaining = client->export_meta.count;
+ int contexts_remaining = request->contexts->count;
- if (client->export_meta.base_allocation) {
+ if (!request->len) {
+ return nbd_send_generic_reply(client, request, -EINVAL,
+ "need non-zero length", errp);
+ }
+ if (request->contexts->base_allocation) {
ret = nbd_co_send_block_status(client, request,
exp->common.blk,
request->from,
@@ -2626,7 +2875,7 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
}
}
- if (client->export_meta.allocation_depth) {
+ if (request->contexts->allocation_depth) {
ret = nbd_co_send_block_status(client, request,
exp->common.blk,
request->from, request->len,
@@ -2639,8 +2888,9 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
}
}
+ assert(request->contexts->exp == client->exp);
for (i = 0; i < client->exp->nr_export_bitmaps; i++) {
- if (!client->export_meta.bitmaps[i]) {
+ if (!request->contexts->bitmaps[i]) {
continue;
}
ret = nbd_co_send_bitmap(client, request,
@@ -2656,6 +2906,10 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
assert(!contexts_remaining);
return 0;
+ } else if (client->contexts.count) {
+ return nbd_send_generic_reply(client, request, -EINVAL,
+ "CMD_BLOCK_STATUS payload not valid",
+ errp);
} else {
return nbd_send_generic_reply(client, request, -EINVAL,
"CMD_BLOCK_STATUS not negotiated",
@@ -2734,13 +2988,19 @@ static coroutine_fn void nbd_trip(void *opaque)
} else {
ret = nbd_handle_request(client, &request, req->data, &local_err);
}
+ if (request.contexts && request.contexts != &client->contexts) {
+ assert(request.type == NBD_CMD_BLOCK_STATUS);
+ g_free(request.contexts->bitmaps);
+ g_free(request.contexts);
+ }
if (ret < 0) {
error_prepend(&local_err, "Failed to send reply: ");
goto disconnect;
}
- /* We must disconnect after NBD_CMD_WRITE if we did not
- * read the payload.
+ /*
+ * We must disconnect after NBD_CMD_WRITE or BLOCK_STATUS with
+ * payload if we did not read the payload.
*/
if (!req->complete) {
error_setg(&local_err, "Request handling failed in intermediate state");
diff --git a/nbd/trace-events b/nbd/trace-events
index f9dccfc..00ae321 100644
--- a/nbd/trace-events
+++ b/nbd/trace-events
@@ -33,7 +33,8 @@ nbd_client_clear_queue(void) "Clearing NBD queue"
nbd_client_clear_socket(void) "Clearing NBD socket"
nbd_send_request(uint64_t from, uint64_t len, uint64_t cookie, uint16_t flags, uint16_t type, const char *name) "Sending request to server: { .from = %" PRIu64", .len = %" PRIu64 ", .cookie = %" PRIu64 ", .flags = 0x%" PRIx16 ", .type = %" PRIu16 " (%s) }"
nbd_receive_simple_reply(int32_t error, const char *errname, uint64_t cookie) "Got simple reply: { .error = %" PRId32 " (%s), cookie = %" PRIu64" }"
-nbd_receive_structured_reply_chunk(uint16_t flags, uint16_t type, const char *name, uint64_t cookie, uint32_t length) "Got structured reply chunk: { flags = 0x%" PRIx16 ", type = %d (%s), cookie = %" PRIu64 ", length = %" PRIu32 " }"
+nbd_receive_reply_chunk_header(uint16_t flags, uint16_t type, const char *name, uint64_t cookie, uint32_t length) "Got reply chunk header: { flags = 0x%" PRIx16 ", type = %" PRIu16 " (%s), cookie = %" PRIu64 ", length = %" PRIu32 " }"
+nbd_receive_wrong_header(uint32_t magic, const char *mode) "Server sent unexpected magic 0x%" PRIx32 " for negotiated mode %s"
# common.c
nbd_unknown_error(int err) "Squashing unexpected error %d to EINVAL"
@@ -69,8 +70,10 @@ nbd_co_send_chunk_read(uint64_t cookie, uint64_t offset, void *data, uint64_t si
nbd_co_send_chunk_read_hole(uint64_t cookie, uint64_t offset, uint64_t size) "Send structured read hole reply: cookie = %" PRIu64 ", offset = %" PRIu64 ", len = %" PRIu64
nbd_co_send_extents(uint64_t cookie, unsigned int extents, uint32_t id, uint64_t length, int last) "Send block status reply: cookie = %" PRIu64 ", extents = %u, context = %d (extents cover %" PRIu64 " bytes, last chunk = %d)"
nbd_co_send_chunk_error(uint64_t cookie, int err, const char *errname, const char *msg) "Send structured error reply: cookie = %" PRIu64 ", error = %d (%s), msg = '%s'"
+nbd_co_receive_block_status_payload_compliance(uint64_t from, uint64_t len) "client sent unusable block status payload: from=0x%" PRIx64 ", len=0x%" PRIx64
nbd_co_receive_request_decode_type(uint64_t cookie, uint16_t type, const char *name) "Decoding type: cookie = %" PRIu64 ", type = %" PRIu16 " (%s)"
nbd_co_receive_request_payload_received(uint64_t cookie, uint64_t len) "Payload received: cookie = %" PRIu64 ", len = %" PRIu64
+nbd_co_receive_ext_payload_compliance(uint64_t from, uint64_t len) "client sent non-compliant write without payload flag: from=0x%" PRIx64 ", len=0x%" PRIx64
nbd_co_receive_align_compliance(const char *op, uint64_t from, uint64_t len, uint32_t align) "client sent non-compliant unaligned %s request: from=0x%" PRIx64 ", len=0x%" PRIx64 ", align=0x%" PRIx32
nbd_trip(void) "Reading request"
diff --git a/net/net.c b/net/net.c
index 1c0bfda..c0c0cbe 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1677,7 +1677,7 @@ void net_init_clients(void)
* Modern syntax is to be parsed with netdev_parse_modern().
* Traditional syntax is to be parsed with net_client_parse().
*/
-bool netdev_is_modern(const char *optarg)
+bool netdev_is_modern(const char *optstr)
{
QemuOpts *opts;
bool is_modern;
@@ -1689,13 +1689,13 @@ bool netdev_is_modern(const char *optarg)
.desc = { { } },
};
- if (optarg[0] == '{') {
+ if (optstr[0] == '{') {
/* This is JSON, which means it's modern syntax */
return true;
}
opts = qemu_opts_create(&dummy_opts, NULL, false, &error_abort);
- qemu_opts_do_parse(opts, optarg, dummy_opts.implied_opt_name,
+ qemu_opts_do_parse(opts, optstr, dummy_opts.implied_opt_name,
&error_abort);
type = qemu_opt_get(opts, "type");
is_modern = !g_strcmp0(type, "stream") || !g_strcmp0(type, "dgram");
@@ -1711,12 +1711,12 @@ bool netdev_is_modern(const char *optarg)
* netdev_parse_modern() appends to @nd_queue, whereas net_client_parse()
* appends to @qemu_netdev_opts.
*/
-void netdev_parse_modern(const char *optarg)
+void netdev_parse_modern(const char *optstr)
{
Visitor *v;
NetdevQueueEntry *nd;
- v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
+ v = qobject_input_visitor_new_str(optstr, "type", &error_fatal);
nd = g_new(NetdevQueueEntry, 1);
visit_type_Netdev(v, NULL, &nd->nd, &error_fatal);
visit_free(v);
@@ -1725,9 +1725,9 @@ void netdev_parse_modern(const char *optarg)
QSIMPLEQ_INSERT_TAIL(&nd_queue, nd, entry);
}
-void net_client_parse(QemuOptsList *opts_list, const char *optarg)
+void net_client_parse(QemuOptsList *opts_list, const char *optstr)
{
- if (!qemu_opts_parse_noisily(opts_list, optarg, true)) {
+ if (!qemu_opts_parse_noisily(opts_list, optstr, true)) {
exit(1);
}
}
diff --git a/os-posix.c b/os-posix.c
index f90dfda..52ef699 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -94,13 +94,13 @@ static uid_t user_uid = (uid_t)-1; /* -1 -1 >=0 */
static gid_t user_gid = (gid_t)-1; /* -1 -1 >=0 */
/*
- * Prepare to change user ID. optarg can be one of 3 forms:
+ * Prepare to change user ID. user_id can be one of 3 forms:
* - a username, in which case user ID will be changed to its uid,
* with primary and supplementary groups set up too;
* - a numeric uid, in which case only the uid will be set;
* - a pair of numeric uid:gid.
*/
-bool os_set_runas(const char *optarg)
+bool os_set_runas(const char *user_id)
{
unsigned long lv;
const char *ep;
@@ -108,14 +108,14 @@ bool os_set_runas(const char *optarg)
gid_t got_gid;
int rc;
- user_pwd = getpwnam(optarg);
+ user_pwd = getpwnam(user_id);
if (user_pwd) {
user_uid = -1;
user_gid = -1;
return true;
}
- rc = qemu_strtoul(optarg, &ep, 0, &lv);
+ rc = qemu_strtoul(user_id, &ep, 0, &lv);
got_uid = lv; /* overflow here is ID in C99 */
if (rc || *ep != ':' || got_uid != lv || got_uid == (uid_t)-1) {
return false;
@@ -173,9 +173,9 @@ static void change_process_uid(void)
static const char *chroot_dir;
-void os_set_chroot(const char *optarg)
+void os_set_chroot(const char *path)
{
- chroot_dir = optarg;
+ chroot_dir = path;
}
static void change_root(void)
diff --git a/plugins/loader.c b/plugins/loader.c
index 809f3f9..734c11c 100644
--- a/plugins/loader.c
+++ b/plugins/loader.c
@@ -140,12 +140,12 @@ static int plugin_add(void *opaque, const char *name, const char *value,
return 0;
}
-void qemu_plugin_opt_parse(const char *optarg, QemuPluginList *head)
+void qemu_plugin_opt_parse(const char *optstr, QemuPluginList *head)
{
struct qemu_plugin_parse_arg arg;
QemuOpts *opts;
- opts = qemu_opts_parse_noisily(qemu_find_opts("plugin"), optarg, true);
+ opts = qemu_opts_parse_noisily(qemu_find_opts("plugin"), optstr, true);
if (opts == NULL) {
exit(1);
}
diff --git a/qapi/migration.json b/qapi/migration.json
index 8843e74..d8f3bbd 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1837,6 +1837,21 @@
'data': ['page-sampling', 'dirty-ring', 'dirty-bitmap'] }
##
+# @TimeUnit:
+#
+# Specifies unit in which time-related value is specified.
+#
+# @second: value is in seconds
+#
+# @millisecond: value is in milliseconds
+#
+# Since 8.2
+#
+##
+{ 'enum': 'TimeUnit',
+ 'data': ['second', 'millisecond'] }
+
+##
# @DirtyRateInfo:
#
# Information about measured dirty page rate.
@@ -1848,8 +1863,10 @@
#
# @start-time: start time in units of second for calculation
#
-# @calc-time: time period for which dirty page rate was measured
-# (in seconds)
+# @calc-time: time period for which dirty page rate was measured,
+# expressed and rounded down to @calc-time-unit.
+#
+# @calc-time-unit: time unit of @calc-time (Since 8.2)
#
# @sample-pages: number of sampled pages per GiB of guest memory.
# Valid only in page-sampling mode (Since 6.1)
@@ -1866,6 +1883,7 @@
'status': 'DirtyRateStatus',
'start-time': 'int64',
'calc-time': 'int64',
+ 'calc-time-unit': 'TimeUnit',
'sample-pages': 'uint64',
'mode': 'DirtyRateMeasureMode',
'*vcpu-dirty-rate': [ 'DirtyRateVcpu' ] } }
@@ -1901,12 +1919,16 @@
# This mode tracks page modification per each vCPU separately. It
# requires that KVM accelerator property "dirty-ring-size" is set.
#
-# @calc-time: time period in units of second for which dirty page rate
-# is calculated. Note that larger @calc-time values will
-# typically result in smaller dirty page rates because page
-# dirtying is a one-time event. Once some page is counted as
-# dirty during @calc-time period, further writes to this page will
-# not increase dirty page rate anymore.
+# @calc-time: time period for which dirty page rate is calculated.
+# By default it is specified in seconds, but the unit can be set
+# explicitly with @calc-time-unit. Note that larger @calc-time
+# values will typically result in smaller dirty page rates because
+# page dirtying is a one-time event. Once some page is counted
+# as dirty during @calc-time period, further writes to this page
+# will not increase dirty page rate anymore.
+#
+# @calc-time-unit: time unit in which @calc-time is specified.
+# By default it is seconds. (Since 8.2)
#
# @sample-pages: number of sampled pages per each GiB of guest memory.
# Default value is 512. For 4KiB guest pages this corresponds to
@@ -1924,8 +1946,16 @@
# -> {"execute": "calc-dirty-rate", "arguments": {"calc-time": 1,
# 'sample-pages': 512} }
# <- { "return": {} }
+#
+# Measure dirty rate using dirty bitmap for 500 milliseconds:
+#
+# -> {"execute": "calc-dirty-rate", "arguments": {"calc-time": 500,
+# "calc-time-unit": "millisecond", "mode": "dirty-bitmap"} }
+#
+# <- { "return": {} }
##
{ 'command': 'calc-dirty-rate', 'data': {'calc-time': 'int64',
+ '*calc-time-unit': 'TimeUnit',
'*sample-pages': 'int',
'*mode': 'DirtyRateMeasureMode'} }
@@ -1934,6 +1964,9 @@
#
# Query results of the most recent invocation of @calc-dirty-rate.
#
+# @calc-time-unit: time unit in which to report calculation time.
+# By default it is reported in seconds. (Since 8.2)
+#
# Since: 5.2
#
# Examples:
@@ -1941,14 +1974,17 @@
# 1. Measurement is in progress:
#
# <- {"status": "measuring", "sample-pages": 512,
-# "mode": "page-sampling", "start-time": 3665220, "calc-time": 10}
+# "mode": "page-sampling", "start-time": 1693900454, "calc-time": 10,
+# "calc-time-unit": "second"}
#
# 2. Measurement has been completed:
#
# <- {"status": "measured", "sample-pages": 512, "dirty-rate": 108,
-# "mode": "page-sampling", "start-time": 3665220, "calc-time": 10}
+# "mode": "page-sampling", "start-time": 1693900454, "calc-time": 10,
+# "calc-time-unit": "second"}
##
-{ 'command': 'query-dirty-rate', 'returns': 'DirtyRateInfo' }
+{ 'command': 'query-dirty-rate', 'data': {'*calc-time-unit': 'TimeUnit' },
+ 'returns': 'DirtyRateInfo' }
##
# @DirtyLimitInfo:
diff --git a/qemu-img.c b/qemu-img.c
index a48edb7..6068ab0 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -235,25 +235,25 @@ void help(void)
}
/*
- * Is @optarg safe for accumulate_options()?
+ * Is @list safe for accumulate_options()?
* It is when multiple of them can be joined together separated by ','.
- * To make that work, @optarg must not start with ',' (or else a
+ * To make that work, @list must not start with ',' (or else a
* separating ',' preceding it gets escaped), and it must not end with
* an odd number of ',' (or else a separating ',' following it gets
* escaped), or be empty (or else a separating ',' preceding it can
* escape a separating ',' following it).
*
*/
-static bool is_valid_option_list(const char *optarg)
+static bool is_valid_option_list(const char *list)
{
- size_t len = strlen(optarg);
+ size_t len = strlen(list);
size_t i;
- if (!optarg[0] || optarg[0] == ',') {
+ if (!list[0] || list[0] == ',') {
return false;
}
- for (i = len; i > 0 && optarg[i - 1] == ','; i--) {
+ for (i = len; i > 0 && list[i - 1] == ','; i--) {
}
if ((len - i) % 2) {
return false;
@@ -262,19 +262,19 @@ static bool is_valid_option_list(const char *optarg)
return true;
}
-static int accumulate_options(char **options, char *optarg)
+static int accumulate_options(char **options, char *list)
{
char *new_options;
- if (!is_valid_option_list(optarg)) {
- error_report("Invalid option list: %s", optarg);
+ if (!is_valid_option_list(list)) {
+ error_report("Invalid option list: %s", list);
return -1;
}
if (!*options) {
- *options = g_strdup(optarg);
+ *options = g_strdup(list);
} else {
- new_options = g_strdup_printf("%s,%s", *options, optarg);
+ new_options = g_strdup_printf("%s,%s", *options, list);
g_free(*options);
*options = new_options;
}
diff --git a/qemu-io.c b/qemu-io.c
index 2bd7bfb..050c708 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -475,10 +475,10 @@ static int command_loop(void)
return last_error;
}
-static void add_user_command(char *optarg)
+static void add_user_command(char *user_cmd)
{
cmdline = g_renew(char *, cmdline, ++ncmdline);
- cmdline[ncmdline-1] = optarg;
+ cmdline[ncmdline - 1] = user_cmd;
}
static void reenable_tty_echo(void)
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 54faa87..186e646 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -219,6 +219,7 @@ static int qemu_nbd_client_list(SocketAddress *saddr, QCryptoTLSCreds *tls,
[NBD_FLAG_SEND_RESIZE_BIT] = "resize",
[NBD_FLAG_SEND_CACHE_BIT] = "cache",
[NBD_FLAG_SEND_FAST_ZERO_BIT] = "fast-zero",
+ [NBD_FLAG_BLOCK_STAT_PAYLOAD_BIT] = "block-status-payload",
};
printf(" size: %" PRIu64 "\n", list[i].size);
@@ -235,6 +236,9 @@ static int qemu_nbd_client_list(SocketAddress *saddr, QCryptoTLSCreds *tls,
printf(" opt block: %u\n", list[i].opt_block);
printf(" max block: %u\n", list[i].max_block);
}
+ printf(" transaction size: %s\n",
+ list[i].mode >= NBD_MODE_EXTENDED ?
+ "64-bit" : "32-bit");
if (list[i].n_contexts) {
printf(" available meta contexts: %d\n", list[i].n_contexts);
for (j = 0; j < list[i].n_contexts; j++) {
diff --git a/qemu-options.hx b/qemu-options.hx
index 840b83d..54a7e94 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -728,20 +728,22 @@ ERST
DEF("audio", HAS_ARG, QEMU_OPTION_audio,
+ "-audio [driver=]driver[,prop[=value][,...]]\n"
+ " specifies default audio backend when `audiodev` is not\n"
+ " used to create a machine or sound device;"
+ " options are the same as for -audiodev\n"
"-audio [driver=]driver,model=value[,prop[=value][,...]]\n"
" specifies the audio backend and device to use;\n"
" apart from 'model', options are the same as for -audiodev.\n"
" use '-audio model=help' to show possible devices.\n",
QEMU_ARCH_ALL)
SRST
-``-audio [driver=]driver,model=value[,prop[=value][,...]]``
- This option is a shortcut for configuring both the guest audio
- hardware and the host audio backend in one go.
- The driver option is the same as with the corresponding ``-audiodev`` option below.
- The guest hardware model can be set with ``model=modelname``.
-
- Use ``driver=help`` to list the available drivers,
- and ``model=help`` to list the available device types.
+``-audio [driver=]driver[,model=value][,prop[=value][,...]]``
+ If the ``model`` option is specified, ``-audio`` is a shortcut
+ for configuring both the guest audio hardware and the host audio
+ backend in one go. The guest hardware model can be set with
+ ``model=modelname``. Use ``model=help`` to list the available
+ device types.
The following two example do exactly the same, to show how ``-audio``
can be used to shorten the command line length:
@@ -750,6 +752,17 @@ SRST
|qemu_system| -audiodev pa,id=pa -device sb16,audiodev=pa
|qemu_system| -audio pa,model=sb16
+
+ If the ``model`` option is not specified, ``-audio`` is used to
+ configure a default audio backend that will be used whenever the
+ ``audiodev`` property is not set on a device or machine. In
+ particular, ``-audio none`` ensures that no audio is produced even
+ for machines that have embedded sound hardware.
+
+ In both cases, the driver option is the same as with the corresponding
+ ``-audiodev`` option below. Use ``driver=help`` to list the available
+ drivers.
+
ERST
DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev,
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index 7d31589..e0833c8 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -259,7 +259,7 @@ static void user_creatable_print_help_from_qdict(QDict *args)
}
}
-ObjectOptions *user_creatable_parse_str(const char *optarg, Error **errp)
+ObjectOptions *user_creatable_parse_str(const char *str, Error **errp)
{
ERRP_GUARD();
QObject *obj;
@@ -267,14 +267,14 @@ ObjectOptions *user_creatable_parse_str(const char *optarg, Error **errp)
Visitor *v;
ObjectOptions *options;
- if (optarg[0] == '{') {
- obj = qobject_from_json(optarg, errp);
+ if (str[0] == '{') {
+ obj = qobject_from_json(str, errp);
if (!obj) {
return NULL;
}
v = qobject_input_visitor_new(obj);
} else {
- QDict *args = keyval_parse(optarg, "qom-type", &help, errp);
+ QDict *args = keyval_parse(str, "qom-type", &help, errp);
if (*errp) {
return NULL;
}
@@ -295,12 +295,12 @@ ObjectOptions *user_creatable_parse_str(const char *optarg, Error **errp)
return options;
}
-bool user_creatable_add_from_str(const char *optarg, Error **errp)
+bool user_creatable_add_from_str(const char *str, Error **errp)
{
ERRP_GUARD();
ObjectOptions *options;
- options = user_creatable_parse_str(optarg, errp);
+ options = user_creatable_parse_str(str, errp);
if (!options) {
return false;
}
@@ -310,9 +310,9 @@ bool user_creatable_add_from_str(const char *optarg, Error **errp)
return !*errp;
}
-void user_creatable_process_cmdline(const char *optarg)
+void user_creatable_process_cmdline(const char *cmdline)
{
- if (!user_creatable_add_from_str(optarg, &error_fatal)) {
+ if (!user_creatable_add_from_str(cmdline, &error_fatal)) {
/* Help was printed */
exit(EXIT_SUCCESS);
}
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 1ad9ccb..6e4100d 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -466,7 +466,7 @@ sub top_of_kernel_tree {
my @tree_check = (
"COPYING", "MAINTAINERS", "Makefile",
"README.rst", "docs", "VERSION",
- "linux-user", "softmmu"
+ "linux-user", "system"
);
foreach my $check (@tree_check) {
diff --git a/scripts/coverity-scan/COMPONENTS.md b/scripts/coverity-scan/COMPONENTS.md
index 883da95..0e62f10 100644
--- a/scripts/coverity-scan/COMPONENTS.md
+++ b/scripts/coverity-scan/COMPONENTS.md
@@ -148,7 +148,7 @@ tcg
~ (/qemu)?(/accel/tcg|/replay|/tcg)/.*
sysemu
- ~ (/qemu)?(/softmmu/.*|/accel/.*)
+ ~ (/qemu)?(/system/.*|/accel/.*)
(headers)
~ (/qemu)?(/include/.*)
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index e5499b9..02fa828 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -796,7 +796,7 @@ sub top_of_tree {
&& (-d "${lk_path}docs")
&& (-f "${lk_path}VERSION")
&& (-d "${lk_path}linux-user/")
- && (-d "${lk_path}softmmu/")) {
+ && (-d "${lk_path}system/")) {
return 1;
}
return 0;
diff --git a/scripts/oss-fuzz/build.sh b/scripts/oss-fuzz/build.sh
index 3bda0d7..5238f83 100755
--- a/scripts/oss-fuzz/build.sh
+++ b/scripts/oss-fuzz/build.sh
@@ -43,10 +43,10 @@ EXTRA_CFLAGS="$CFLAGS -U __OPTIMIZE__"
if ! { [ -e "./COPYING" ] &&
[ -e "./MAINTAINERS" ] &&
[ -e "./Makefile" ] &&
- [ -e "./docs" ] &&
+ [ -d "./docs" ] &&
[ -e "./VERSION" ] &&
- [ -e "./linux-user" ] &&
- [ -e "./softmmu" ];} ; then
+ [ -d "./linux-user" ] &&
+ [ -d "./system" ];} ; then
fatal "Please run the script from the top of the QEMU tree"
fi
diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
index 29c5670..329ea11 100644
--- a/semihosting/arm-compat-semi.c
+++ b/semihosting/arm-compat-semi.c
@@ -202,13 +202,13 @@ static LayoutInfo common_semi_find_bases(CPUState *cs)
* The semihosting API has no concept of its errno being thread-safe,
* as the API design predates SMP CPUs and was intended as a simple
* real-hardware set of debug functionality. For QEMU, we make the
- * errno be per-thread in linux-user mode; in softmmu it is a simple
+ * errno be per-thread in linux-user mode; in system-mode it is a simple
* global, and we assume that the guest takes care of avoiding any races.
*/
#ifndef CONFIG_USER_ONLY
static target_ulong syscall_err;
-#include "semihosting/softmmu-uaccess.h"
+#include "semihosting/uaccess.h"
#endif
static inline uint32_t get_swi_errno(CPUState *cs)
@@ -367,7 +367,6 @@ void do_common_semihosting(CPUState *cs)
target_ulong ul_ret;
char * s;
int nr;
- uint32_t ret;
int64_t elapsed;
nr = common_semi_arg(cs, 0) & 0xffffffffU;
@@ -725,6 +724,9 @@ void do_common_semihosting(CPUState *cs)
case TARGET_SYS_EXIT:
case TARGET_SYS_EXIT_EXTENDED:
+ {
+ uint32_t ret;
+
if (common_semi_sys_exit_extended(cs, nr)) {
/*
* The A64 version of SYS_EXIT takes a parameter block,
@@ -752,6 +754,7 @@ void do_common_semihosting(CPUState *cs)
}
gdb_exit(ret);
exit(ret);
+ }
case TARGET_SYS_ELAPSED:
elapsed = get_clock() - clock_start;
diff --git a/semihosting/config.c b/semihosting/config.c
index 8ca5697..249a377 100644
--- a/semihosting/config.c
+++ b/semihosting/config.c
@@ -12,7 +12,7 @@
* linux-user targets. However in that use case no configuration of
* the outputs and command lines is supported.
*
- * The config module is common to all softmmu targets however as vl.c
+ * The config module is common to all system targets however as vl.c
* needs to link against the helpers.
*
* SPDX-License-Identifier: GPL-2.0-or-later
@@ -131,10 +131,10 @@ void qemu_semihosting_enable(void)
semihosting.target = SEMIHOSTING_TARGET_AUTO;
}
-int qemu_semihosting_config_options(const char *optarg)
+int qemu_semihosting_config_options(const char *optstr)
{
QemuOptsList *opt_list = qemu_find_opts("semihosting-config");
- QemuOpts *opts = qemu_opts_parse_noisily(opt_list, optarg, false);
+ QemuOpts *opts = qemu_opts_parse_noisily(opt_list, optstr, false);
semihosting.enabled = true;
@@ -155,7 +155,7 @@ int qemu_semihosting_config_options(const char *optarg)
semihosting.target = SEMIHOSTING_TARGET_AUTO;
} else {
error_report("unsupported semihosting-config %s",
- optarg);
+ optstr);
return 1;
}
} else {
@@ -165,7 +165,7 @@ int qemu_semihosting_config_options(const char *optarg)
qemu_opt_foreach(opts, add_semihosting_arg,
&semihosting, NULL);
} else {
- error_report("unsupported semihosting-config %s", optarg);
+ error_report("unsupported semihosting-config %s", optstr);
return 1;
}
diff --git a/semihosting/guestfd.c b/semihosting/guestfd.c
index acb86b5..955c2ef 100644
--- a/semihosting/guestfd.c
+++ b/semihosting/guestfd.c
@@ -15,7 +15,7 @@
#ifdef CONFIG_USER_ONLY
#include "qemu.h"
#else
-#include "semihosting/softmmu-uaccess.h"
+#include "semihosting/uaccess.h"
#include CONFIG_DEVICES
#endif
diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c
index 1ab4809..c40348f 100644
--- a/semihosting/syscalls.c
+++ b/semihosting/syscalls.c
@@ -15,7 +15,7 @@
#ifdef CONFIG_USER_ONLY
#include "qemu.h"
#else
-#include "semihosting/softmmu-uaccess.h"
+#include "semihosting/uaccess.h"
#endif
diff --git a/semihosting/uaccess.c b/semihosting/uaccess.c
index 7505eb6..5d889f9 100644
--- a/semihosting/uaccess.c
+++ b/semihosting/uaccess.c
@@ -9,9 +9,9 @@
#include "qemu/osdep.h"
#include "exec/exec-all.h"
-#include "semihosting/softmmu-uaccess.h"
+#include "semihosting/uaccess.h"
-void *softmmu_lock_user(CPUArchState *env, target_ulong addr,
+void *uaccess_lock_user(CPUArchState *env, target_ulong addr,
target_ulong len, bool copy)
{
void *p = malloc(len);
@@ -24,7 +24,7 @@ void *softmmu_lock_user(CPUArchState *env, target_ulong addr,
return p;
}
-ssize_t softmmu_strlen_user(CPUArchState *env, target_ulong addr)
+ssize_t uaccess_strlen_user(CPUArchState *env, target_ulong addr)
{
int mmu_idx = cpu_mmu_index(env, false);
size_t len = 0;
@@ -72,16 +72,16 @@ ssize_t softmmu_strlen_user(CPUArchState *env, target_ulong addr)
}
}
-char *softmmu_lock_user_string(CPUArchState *env, target_ulong addr)
+char *uaccess_lock_user_string(CPUArchState *env, target_ulong addr)
{
- ssize_t len = softmmu_strlen_user(env, addr);
+ ssize_t len = uaccess_strlen_user(env, addr);
if (len < 0) {
return NULL;
}
- return softmmu_lock_user(env, addr, len + 1, true);
+ return uaccess_lock_user(env, addr, len + 1, true);
}
-void softmmu_unlock_user(CPUArchState *env, void *p,
+void uaccess_unlock_user(CPUArchState *env, void *p,
target_ulong addr, target_ulong len)
{
if (len) {
diff --git a/softmmu/trace.h b/softmmu/trace.h
deleted file mode 100644
index 2ad1011..0000000
--- a/softmmu/trace.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "trace/trace-softmmu.h"
diff --git a/stubs/semihost.c b/stubs/semihost.c
index aad7a70..f26cbb7 100644
--- a/stubs/semihost.c
+++ b/stubs/semihost.c
@@ -1,9 +1,9 @@
/*
- * Semihosting Stubs for SoftMMU
+ * Semihosting Stubs for system emulation
*
* Copyright (c) 2019 Linaro Ltd
*
- * Stubs for SoftMMU targets that don't actually do semihosting.
+ * Stubs for system targets that don't actually do semihosting.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@@ -36,7 +36,7 @@ void qemu_semihosting_enable(void)
{
}
-int qemu_semihosting_config_options(const char *optarg)
+int qemu_semihosting_config_options(const char *optstr)
{
return 1;
}
diff --git a/softmmu/arch_init.c b/system/arch_init.c
index 79716f9..79716f9 100644
--- a/softmmu/arch_init.c
+++ b/system/arch_init.c
diff --git a/softmmu/async-teardown.c b/system/async-teardown.c
index 396963c..396963c 100644
--- a/softmmu/async-teardown.c
+++ b/system/async-teardown.c
diff --git a/softmmu/balloon.c b/system/balloon.c
index e0e8969..e0e8969 100644
--- a/softmmu/balloon.c
+++ b/system/balloon.c
diff --git a/softmmu/bootdevice.c b/system/bootdevice.c
index 2106f10..2106f10 100644
--- a/softmmu/bootdevice.c
+++ b/system/bootdevice.c
diff --git a/softmmu/cpu-throttle.c b/system/cpu-throttle.c
index d9bb30a..d9bb30a 100644
--- a/softmmu/cpu-throttle.c
+++ b/system/cpu-throttle.c
diff --git a/softmmu/cpu-timers.c b/system/cpu-timers.c
index 117408c..7452d97 100644
--- a/softmmu/cpu-timers.c
+++ b/system/cpu-timers.c
@@ -36,7 +36,7 @@
#include "hw/core/cpu.h"
#include "sysemu/cpu-timers.h"
#include "sysemu/cpu-throttle.h"
-#include "timers-state.h"
+#include "sysemu/cpu-timers-internal.h"
/* clock and ticks */
diff --git a/softmmu/cpus.c b/system/cpus.c
index 0848e0d..0848e0d 100644
--- a/softmmu/cpus.c
+++ b/system/cpus.c
diff --git a/softmmu/datadir.c b/system/datadir.c
index c9237cb..c9237cb 100644
--- a/softmmu/datadir.c
+++ b/system/datadir.c
diff --git a/softmmu/device_tree.c b/system/device_tree.c
index eb5166c..eb5166c 100644
--- a/softmmu/device_tree.c
+++ b/system/device_tree.c
diff --git a/softmmu/dirtylimit.c b/system/dirtylimit.c
index fa959d7..fa959d7 100644
--- a/softmmu/dirtylimit.c
+++ b/system/dirtylimit.c
diff --git a/softmmu/dma-helpers.c b/system/dma-helpers.c
index 36211ac..36211ac 100644
--- a/softmmu/dma-helpers.c
+++ b/system/dma-helpers.c
diff --git a/softmmu/globals.c b/system/globals.c
index e83b542..e83b542 100644
--- a/softmmu/globals.c
+++ b/system/globals.c
diff --git a/softmmu/ioport.c b/system/ioport.c
index 1824aa8..1824aa8 100644
--- a/softmmu/ioport.c
+++ b/system/ioport.c
diff --git a/softmmu/main.c b/system/main.c
index 694388b..694388b 100644
--- a/softmmu/main.c
+++ b/system/main.c
diff --git a/softmmu/memory.c b/system/memory.c
index 234bd7b..fa1c99f 100644
--- a/softmmu/memory.c
+++ b/system/memory.c
@@ -3638,7 +3638,7 @@ void memory_region_init_rom_device(MemoryRegion *mr,
}
/*
- * Support softmmu builds with CONFIG_FUZZ using a weak symbol and a stub for
+ * Support system builds with CONFIG_FUZZ using a weak symbol and a stub for
* the fuzz_dma_read_cb callback
*/
#ifdef CONFIG_FUZZ
diff --git a/softmmu/memory_mapping.c b/system/memory_mapping.c
index d7f1d09..d7f1d09 100644
--- a/softmmu/memory_mapping.c
+++ b/system/memory_mapping.c
diff --git a/softmmu/meson.build b/system/meson.build
index 3a64dd8..3a64dd8 100644
--- a/softmmu/meson.build
+++ b/system/meson.build
diff --git a/softmmu/physmem.c b/system/physmem.c
index 309653c..edc3ed8 100644
--- a/softmmu/physmem.c
+++ b/system/physmem.c
@@ -2301,8 +2301,10 @@ RAMBlock *qemu_ram_block_by_name(const char *name)
return NULL;
}
-/* Some of the softmmu routines need to translate from a host pointer
- (typically a TLB entry) back to a ram offset. */
+/*
+ * Some of the system routines need to translate from a host pointer
+ * (typically a TLB entry) back to a ram offset.
+ */
ram_addr_t qemu_ram_addr_from_host(void *ptr)
{
RAMBlock *block;
diff --git a/softmmu/qdev-monitor.c b/system/qdev-monitor.c
index 74f4e41..74f4e41 100644
--- a/softmmu/qdev-monitor.c
+++ b/system/qdev-monitor.c
diff --git a/softmmu/qemu-seccomp.c b/system/qemu-seccomp.c
index 4d7439e..4d7439e 100644
--- a/softmmu/qemu-seccomp.c
+++ b/system/qemu-seccomp.c
diff --git a/softmmu/qtest.c b/system/qtest.c
index 35b643a..35b643a 100644
--- a/softmmu/qtest.c
+++ b/system/qtest.c
diff --git a/softmmu/rtc.c b/system/rtc.c
index 4904581..4904581 100644
--- a/softmmu/rtc.c
+++ b/system/rtc.c
diff --git a/softmmu/runstate-action.c b/system/runstate-action.c
index ae0761a..ae0761a 100644
--- a/softmmu/runstate-action.c
+++ b/system/runstate-action.c
diff --git a/softmmu/runstate-hmp-cmds.c b/system/runstate-hmp-cmds.c
index 2df670f..2df670f 100644
--- a/softmmu/runstate-hmp-cmds.c
+++ b/system/runstate-hmp-cmds.c
diff --git a/softmmu/runstate.c b/system/runstate.c
index 1652ed0..1652ed0 100644
--- a/softmmu/runstate.c
+++ b/system/runstate.c
diff --git a/softmmu/tpm-hmp-cmds.c b/system/tpm-hmp-cmds.c
index 9ed6ad6..9ed6ad6 100644
--- a/softmmu/tpm-hmp-cmds.c
+++ b/system/tpm-hmp-cmds.c
diff --git a/softmmu/tpm.c b/system/tpm.c
index 578563f..7164ea7 100644
--- a/softmmu/tpm.c
+++ b/system/tpm.c
@@ -175,15 +175,15 @@ int tpm_init(void)
* Parse the TPM configuration options.
* To display all available TPM backends the user may use '-tpmdev help'
*/
-int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
+int tpm_config_parse(QemuOptsList *opts_list, const char *optstr)
{
QemuOpts *opts;
- if (!strcmp(optarg, "help")) {
+ if (!strcmp(optstr, "help")) {
tpm_display_backend_drivers();
return -1;
}
- opts = qemu_opts_parse_noisily(opts_list, optarg, true);
+ opts = qemu_opts_parse_noisily(opts_list, optstr, true);
if (!opts) {
return -1;
}
diff --git a/softmmu/trace-events b/system/trace-events
index 22606dc..69c9044 100644
--- a/softmmu/trace-events
+++ b/system/trace-events
@@ -21,7 +21,7 @@ flatview_destroy(void *view, void *root) "%p (root %p)"
flatview_destroy_rcu(void *view, void *root) "%p (root %p)"
global_dirty_changed(unsigned int bitmask) "bitmask 0x%"PRIx32
-# softmmu.c
+# cpus.c
vm_stop_flush_all(int ret) "ret %d"
# vl.c
diff --git a/system/trace.h b/system/trace.h
new file mode 100644
index 0000000..cd0136d
--- /dev/null
+++ b/system/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-system.h"
diff --git a/softmmu/vl.c b/system/vl.c
index 98e071e..ba83040 100644
--- a/softmmu/vl.c
+++ b/system/vl.c
@@ -184,6 +184,7 @@ static const char *qtest_log;
static bool opt_one_insn_per_tb;
static int has_defaults = 1;
+static int default_audio = 1;
static int default_serial = 1;
static int default_parallel = 1;
static int default_monitor = 1;
@@ -1066,12 +1067,12 @@ static void select_vgahw(const MachineClass *machine_class, const char *p)
}
}
-static void parse_display_qapi(const char *optarg)
+static void parse_display_qapi(const char *str)
{
DisplayOptions *opts;
Visitor *v;
- v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
+ v = qobject_input_visitor_new_str(str, "type", &error_fatal);
visit_type_DisplayOptions(v, NULL, &opts, &error_fatal);
QAPI_CLONE_MEMBERS(DisplayOptions, &dpy, opts);
@@ -1221,21 +1222,21 @@ static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp)
return monitor_init_opts(opts, errp);
}
-static void monitor_parse(const char *optarg, const char *mode, bool pretty)
+static void monitor_parse(const char *str, const char *mode, bool pretty)
{
static int monitor_device_index = 0;
QemuOpts *opts;
const char *p;
char label[32];
- if (strstart(optarg, "chardev:", &p)) {
+ if (strstart(str, "chardev:", &p)) {
snprintf(label, sizeof(label), "%s", p);
} else {
snprintf(label, sizeof(label), "compat_monitor%d",
monitor_device_index);
- opts = qemu_chr_parse_compat(label, optarg, true);
+ opts = qemu_chr_parse_compat(label, str, true);
if (!opts) {
- error_report("parse error: %s", optarg);
+ error_report("parse error: %s", str);
exit(1);
}
}
@@ -1327,6 +1328,7 @@ static void qemu_disable_default_devices(void)
default_sdcard = 0;
}
if (!has_defaults) {
+ default_audio = 0;
default_monitor = 0;
default_net = 0;
default_vga = 0;
@@ -1631,13 +1633,13 @@ static const QEMUOption *lookup_opt(int argc, char **argv,
static MachineClass *select_machine(QDict *qdict, Error **errp)
{
- const char *optarg = qdict_get_try_str(qdict, "type");
+ const char *machine_type = qdict_get_try_str(qdict, "type");
GSList *machines = object_class_get_list(TYPE_MACHINE, false);
MachineClass *machine_class;
Error *local_err = NULL;
- if (optarg) {
- machine_class = find_machine(optarg, machines);
+ if (machine_type) {
+ machine_class = find_machine(machine_type, machines);
qdict_del(qdict, "type");
if (!machine_class) {
error_setg(&local_err, "unsupported machine type");
@@ -1781,20 +1783,20 @@ static void object_option_add_visitor(Visitor *v)
QTAILQ_INSERT_TAIL(&object_opts, opt, next);
}
-static void object_option_parse(const char *optarg)
+static void object_option_parse(const char *str)
{
QemuOpts *opts;
const char *type;
Visitor *v;
- if (optarg[0] == '{') {
- QObject *obj = qobject_from_json(optarg, &error_fatal);
+ if (str[0] == '{') {
+ QObject *obj = qobject_from_json(str, &error_fatal);
v = qobject_input_visitor_new(obj);
qobject_unref(obj);
} else {
opts = qemu_opts_parse_noisily(qemu_find_opts("object"),
- optarg, true);
+ str, true);
if (!opts) {
exit(1);
}
@@ -1963,6 +1965,9 @@ static void qemu_create_early_backends(void)
*/
configure_blockdev(&bdo_queue, machine_class, snapshot);
audio_init_audiodevs();
+ if (default_audio) {
+ audio_create_default_audiodevs();
+ }
}
@@ -2925,14 +2930,16 @@ void qemu_init(int argc, char **argv)
break;
#endif
case QEMU_OPTION_audiodev:
+ default_audio = 0;
audio_parse_option(optarg);
break;
case QEMU_OPTION_audio: {
bool help;
- char *model;
+ char *model = NULL;
Audiodev *dev = NULL;
Visitor *v;
QDict *dict = keyval_parse(optarg, "driver", &help, &error_fatal);
+ default_audio = 0;
if (help || (qdict_haskey(dict, "driver") &&
is_help_option(qdict_get_str(dict, "driver")))) {
audio_help();
@@ -2941,22 +2948,25 @@ void qemu_init(int argc, char **argv)
if (!qdict_haskey(dict, "id")) {
qdict_put_str(dict, "id", "audiodev0");
}
- if (!qdict_haskey(dict, "model")) {
- error_setg(&error_fatal, "Parameter 'model' is missing");
- }
- model = g_strdup(qdict_get_str(dict, "model"));
- qdict_del(dict, "model");
- if (is_help_option(model)) {
- show_valid_soundhw();
- exit(0);
+ if (qdict_haskey(dict, "model")) {
+ model = g_strdup(qdict_get_str(dict, "model"));
+ qdict_del(dict, "model");
+ if (is_help_option(model)) {
+ show_valid_soundhw();
+ exit(0);
+ }
}
v = qobject_input_visitor_new_keyval(QOBJECT(dict));
qobject_unref(dict);
visit_type_Audiodev(v, NULL, &dev, &error_fatal);
visit_free(v);
- audio_define(dev);
- select_soundhw(model, dev->id);
- g_free(model);
+ if (model) {
+ audio_define(dev);
+ select_soundhw(model, dev->id);
+ g_free(model);
+ } else {
+ audio_define_default(dev, &error_fatal);
+ }
break;
}
case QEMU_OPTION_h:
diff --git a/softmmu/watchpoint.c b/system/watchpoint.c
index 45d1f12..45d1f12 100644
--- a/softmmu/watchpoint.c
+++ b/system/watchpoint.c
diff --git a/target/alpha/meson.build b/target/alpha/meson.build
index 3f5253c..d3502dd 100644
--- a/target/alpha/meson.build
+++ b/target/alpha/meson.build
@@ -15,4 +15,4 @@ alpha_system_ss = ss.source_set()
alpha_system_ss.add(files('machine.c'))
target_arch += {'alpha': alpha_ss}
-target_softmmu_arch += {'alpha': alpha_system_ss}
+target_system_arch += {'alpha': alpha_system_ss}
diff --git a/target/arm/meson.build b/target/arm/meson.build
index e645e45..5d04a8e 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -35,4 +35,4 @@ else
endif
target_arch += {'arm': arm_ss}
-target_softmmu_arch += {'arm': arm_system_ss}
+target_system_arch += {'arm': arm_system_ss}
diff --git a/target/avr/meson.build b/target/avr/meson.build
index a24cf6d..3e172bd 100644
--- a/target/avr/meson.build
+++ b/target/avr/meson.build
@@ -17,4 +17,4 @@ avr_ss.add(files(
avr_system_ss.add(files('machine.c'))
target_arch += {'avr': avr_ss}
-target_softmmu_arch += {'avr': avr_system_ss}
+target_system_arch += {'avr': avr_system_ss}
diff --git a/target/cris/meson.build b/target/cris/meson.build
index 07dc3a5..bbfcdf7 100644
--- a/target/cris/meson.build
+++ b/target/cris/meson.build
@@ -14,4 +14,4 @@ cris_system_ss.add(files(
))
target_arch += {'cris': cris_ss}
-target_softmmu_arch += {'cris': cris_system_ss}
+target_system_arch += {'cris': cris_system_ss}
diff --git a/target/hppa/meson.build b/target/hppa/meson.build
index 59b68e8..f47e54f 100644
--- a/target/hppa/meson.build
+++ b/target/hppa/meson.build
@@ -20,4 +20,4 @@ hppa_system_ss.add(files(
))
target_arch += {'hppa': hppa_ss}
-target_softmmu_arch += {'hppa': hppa_system_ss}
+target_system_arch += {'hppa': hppa_system_ss}
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 9fad31b..cec5d2b 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -26,6 +26,7 @@
#include "tcg/helper-tcg.h"
#include "sysemu/reset.h"
#include "sysemu/hvf.h"
+#include "hvf/hvf-i386.h"
#include "kvm/kvm_i386.h"
#include "sev.h"
#include "qapi/error.h"
@@ -718,7 +719,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
CPUID_7_0_EBX_HLE
CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM */
-#if defined CONFIG_SOFTMMU || defined CONFIG_LINUX
+#if !defined CONFIG_USER_ONLY || defined CONFIG_LINUX
#define TCG_7_0_ECX_RDPID CPUID_7_0_ECX_RDPID
#else
#define TCG_7_0_ECX_RDPID 0
diff --git a/target/i386/hvf/hvf-cpu.c b/target/i386/hvf/hvf-cpu.c
index bb0da39..ac617f1 100644
--- a/target/i386/hvf/hvf-cpu.c
+++ b/target/i386/hvf/hvf-cpu.c
@@ -15,6 +15,7 @@
#include "hw/boards.h"
#include "sysemu/hvf.h"
#include "hw/core/accel-cpu.h"
+#include "hvf-i386.h"
static void hvf_cpu_max_instance_init(X86CPU *cpu)
{
diff --git a/target/i386/hvf/hvf-i386.h b/target/i386/hvf/hvf-i386.h
index 95b47c1..e99c02c 100644
--- a/target/i386/hvf/hvf-i386.h
+++ b/target/i386/hvf/hvf-i386.h
@@ -16,11 +16,7 @@
#ifndef HVF_I386_H
#define HVF_I386_H
-#include "qemu/accel.h"
-#include "sysemu/hvf.h"
-#include "sysemu/hvf_int.h"
-#include "cpu.h"
-#include "x86.h"
+uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, int reg);
void hvf_handle_io(CPUArchState *, uint16_t, void *, int, int, int);
diff --git a/target/i386/hvf/x86_cpuid.c b/target/i386/hvf/x86_cpuid.c
index 7323a7a..9380b90 100644
--- a/target/i386/hvf/x86_cpuid.c
+++ b/target/i386/hvf/x86_cpuid.c
@@ -25,6 +25,7 @@
#include "x86.h"
#include "vmx.h"
#include "sysemu/hvf.h"
+#include "hvf-i386.h"
static bool xgetbv(uint32_t cpuid_ecx, uint32_t idx, uint64_t *xcr)
{
diff --git a/target/i386/kvm/meson.build b/target/i386/kvm/meson.build
index 5d9174b..84d9143 100644
--- a/target/i386/kvm/meson.build
+++ b/target/i386/kvm/meson.build
@@ -1,14 +1,14 @@
-i386_softmmu_kvm_ss = ss.source_set()
+i386_kvm_ss = ss.source_set()
-i386_softmmu_kvm_ss.add(files(
+i386_kvm_ss.add(files(
'kvm.c',
'kvm-cpu.c',
))
-i386_softmmu_kvm_ss.add(when: 'CONFIG_XEN_EMU', if_true: files('xen-emu.c'))
+i386_kvm_ss.add(when: 'CONFIG_XEN_EMU', if_true: files('xen-emu.c'))
-i386_softmmu_kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c'))
+i386_kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c'))
i386_system_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
-i386_system_ss.add_all(when: 'CONFIG_KVM', if_true: i386_softmmu_kvm_ss)
+i386_system_ss.add_all(when: 'CONFIG_KVM', if_true: i386_kvm_ss)
diff --git a/target/i386/meson.build b/target/i386/meson.build
index 6f1036d..7c74bfa 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -31,5 +31,5 @@ subdir('hvf')
subdir('tcg')
target_arch += {'i386': i386_ss}
-target_softmmu_arch += {'i386': i386_system_ss}
+target_system_arch += {'i386': i386_system_ss}
target_user_arch += {'i386': i386_user_ss}
diff --git a/target/i386/tcg/misc_helper.c b/target/i386/tcg/misc_helper.c
index 868f36a..babff06 100644
--- a/target/i386/tcg/misc_helper.c
+++ b/target/i386/tcg/misc_helper.c
@@ -134,7 +134,7 @@ void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
target_ulong HELPER(rdpid)(CPUX86State *env)
{
-#if defined CONFIG_SOFTMMU
+#if !defined CONFIG_USER_ONLY
return env->tsc_aux;
#elif defined CONFIG_LINUX && defined CONFIG_GETCPU
unsigned cpu, node;
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 4f12873..d2061ec 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -178,10 +178,10 @@ typedef struct DisasContext {
#else
#define CODE64(S) (((S)->flags & HF_CS64_MASK) != 0)
#endif
-#if defined(CONFIG_SOFTMMU) && !defined(TARGET_X86_64)
-#define LMA(S) false
-#else
+#if defined(CONFIG_USER_ONLY) || defined(TARGET_X86_64)
#define LMA(S) (((S)->flags & HF_LMA_MASK) != 0)
+#else
+#define LMA(S) false
#endif
#ifdef TARGET_X86_64
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 7fbf045..18e8191 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -30,4 +30,4 @@ common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: [files('disas.c'), gen])
loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
target_arch += {'loongarch': loongarch_ss}
-target_softmmu_arch += {'loongarch': loongarch_system_ss}
+target_system_arch += {'loongarch': loongarch_system_ss}
diff --git a/target/m68k/m68k-semi.c b/target/m68k/m68k-semi.c
index 80cd8d7..b4ffb70 100644
--- a/target/m68k/m68k-semi.c
+++ b/target/m68k/m68k-semi.c
@@ -27,7 +27,7 @@
#include "gdbstub/syscalls.h"
#include "gdbstub/helpers.h"
#include "semihosting/syscalls.h"
-#include "semihosting/softmmu-uaccess.h"
+#include "semihosting/uaccess.h"
#include "hw/boards.h"
#include "qemu/log.h"
diff --git a/target/m68k/meson.build b/target/m68k/meson.build
index 355db26..8d3f9ce 100644
--- a/target/m68k/meson.build
+++ b/target/m68k/meson.build
@@ -16,4 +16,4 @@ m68k_system_ss.add(files(
))
target_arch += {'m68k': m68k_ss}
-target_softmmu_arch += {'m68k': m68k_system_ss}
+target_system_arch += {'m68k': m68k_system_ss}
diff --git a/target/microblaze/meson.build b/target/microblaze/meson.build
index 50fd9ff..3ed4fbb 100644
--- a/target/microblaze/meson.build
+++ b/target/microblaze/meson.build
@@ -17,4 +17,4 @@ microblaze_system_ss.add(files(
))
target_arch += {'microblaze': microblaze_ss}
-target_softmmu_arch += {'microblaze': microblaze_system_ss}
+target_system_arch += {'microblaze': microblaze_system_ss}
diff --git a/target/mips/meson.build b/target/mips/meson.build
index f35e8f0..e57ef24 100644
--- a/target/mips/meson.build
+++ b/target/mips/meson.build
@@ -19,5 +19,5 @@ endif
mips_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
target_arch += {'mips': mips_ss}
-target_softmmu_arch += {'mips': mips_system_ss}
+target_system_arch += {'mips': mips_system_ss}
target_user_arch += {'mips': mips_user_ss}
diff --git a/target/mips/tcg/sysemu/mips-semi.c b/target/mips/tcg/sysemu/mips-semi.c
index b3e4e49..5ba06e9 100644
--- a/target/mips/tcg/sysemu/mips-semi.c
+++ b/target/mips/tcg/sysemu/mips-semi.c
@@ -22,7 +22,7 @@
#include "qemu/log.h"
#include "gdbstub/syscalls.h"
#include "gdbstub/helpers.h"
-#include "semihosting/softmmu-uaccess.h"
+#include "semihosting/uaccess.h"
#include "semihosting/semihost.h"
#include "semihosting/console.h"
#include "semihosting/syscalls.h"
diff --git a/target/nios2/meson.build b/target/nios2/meson.build
index 8f0f9dc..12d8abf 100644
--- a/target/nios2/meson.build
+++ b/target/nios2/meson.build
@@ -14,4 +14,4 @@ nios2_system_ss.add(files(
))
target_arch += {'nios2': nios2_ss}
-target_softmmu_arch += {'nios2': nios2_system_ss}
+target_system_arch += {'nios2': nios2_system_ss}
diff --git a/target/nios2/nios2-semi.c b/target/nios2/nios2-semi.c
index 9d0241c..0b84fcb 100644
--- a/target/nios2/nios2-semi.c
+++ b/target/nios2/nios2-semi.c
@@ -26,7 +26,7 @@
#include "gdbstub/syscalls.h"
#include "gdbstub/helpers.h"
#include "semihosting/syscalls.h"
-#include "semihosting/softmmu-uaccess.h"
+#include "semihosting/uaccess.h"
#include "qemu/log.h"
#define HOSTED_EXIT 0
diff --git a/target/openrisc/meson.build b/target/openrisc/meson.build
index c1cd943..31608b6 100644
--- a/target/openrisc/meson.build
+++ b/target/openrisc/meson.build
@@ -22,4 +22,4 @@ openrisc_system_ss.add(files(
))
target_arch += {'openrisc': openrisc_ss}
-target_softmmu_arch += {'openrisc': openrisc_system_ss}
+target_system_arch += {'openrisc': openrisc_system_ss}
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 6fd0068..0a5c3e7 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -2020,13 +2020,13 @@ void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
ppc_avr_t result; \
\
for (i = 0; i < ARRAY_SIZE(r->u32); i++) { \
- uint16_t e = b->u16[hi ? i : i + 4]; \
- uint8_t a = (e >> 15) ? 0xff : 0; \
- uint8_t r = (e >> 10) & 0x1f; \
- uint8_t g = (e >> 5) & 0x1f; \
- uint8_t b = e & 0x1f; \
+ uint16_t _e = b->u16[hi ? i : i + 4]; \
+ uint8_t _a = (_e >> 15) ? 0xff : 0; \
+ uint8_t _r = (_e >> 10) & 0x1f; \
+ uint8_t _g = (_e >> 5) & 0x1f; \
+ uint8_t _b = _e & 0x1f; \
\
- result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b; \
+ result.u32[i] = (_a << 24) | (_r << 16) | (_g << 8) | _b; \
} \
*r = result; \
}
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 51112bd..d0e2dcd 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -960,8 +960,6 @@ int kvm_arch_put_registers(CPUState *cs, int level)
}
if (cap_one_reg) {
- int i;
-
/*
* We deliberately ignore errors here, for kernels which have
* the ONE_REG calls, but don't support the specific
@@ -1262,8 +1260,6 @@ int kvm_arch_get_registers(CPUState *cs)
}
if (cap_one_reg) {
- int i;
-
/*
* We deliberately ignore errors here, for kernels which have
* the ONE_REG calls, but don't support the specific
diff --git a/target/ppc/meson.build b/target/ppc/meson.build
index 4c26350..97ceb6e 100644
--- a/target/ppc/meson.build
+++ b/target/ppc/meson.build
@@ -55,4 +55,4 @@ ppc_system_ss.add(when: 'TARGET_PPC64', if_true: files(
))
target_arch += {'ppc': ppc_ss}
-target_softmmu_arch += {'ppc': ppc_system_ss}
+target_system_arch += {'ppc': ppc_system_ss}
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index 660078b..ff60b21 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -39,4 +39,4 @@ riscv_system_ss.add(files(
))
target_arch += {'riscv': riscv_ss}
-target_softmmu_arch += {'riscv': riscv_system_ss}
+target_system_arch += {'riscv': riscv_system_ss}
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index cba02c1..c9b39fb 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -100,7 +100,7 @@ static inline target_ulong adjust_addr(CPURISCVState *env, target_ulong addr)
/*
* This function checks watchpoint before real load operation.
*
- * In softmmu mode, the TLB API probe_access is enough for watchpoint check.
+ * In system mode, the TLB API probe_access is enough for watchpoint check.
* In user mode, there is no watchpoint support now.
*
* It will trigger an exception if there is no mapping in TLB
diff --git a/target/rx/meson.build b/target/rx/meson.build
index 8de0ad4..d196737 100644
--- a/target/rx/meson.build
+++ b/target/rx/meson.build
@@ -13,4 +13,4 @@ rx_ss.add(files(
'disas.c'))
target_arch += {'rx': rx_ss}
-target_softmmu_arch += {'rx': ss.source_set()}
+target_system_arch += {'rx': ss.source_set()}
diff --git a/target/s390x/meson.build b/target/s390x/meson.build
index 42ed389..02ca43d 100644
--- a/target/s390x/meson.build
+++ b/target/s390x/meson.build
@@ -40,5 +40,5 @@ subdir('tcg')
subdir('kvm')
target_arch += {'s390x': s390x_ss}
-target_softmmu_arch += {'s390x': s390x_system_ss}
+target_system_arch += {'s390x': s390x_system_ss}
target_user_arch += {'s390x': s390x_user_ss}
diff --git a/target/sh4/meson.build b/target/sh4/meson.build
index a78e9ec..fe09f96 100644
--- a/target/sh4/meson.build
+++ b/target/sh4/meson.build
@@ -11,4 +11,4 @@ sh4_system_ss = ss.source_set()
sh4_system_ss.add(files('monitor.c'))
target_arch += {'sh4': sh4_ss}
-target_softmmu_arch += {'sh4': sh4_system_ss}
+target_system_arch += {'sh4': sh4_system_ss}
diff --git a/target/sparc/meson.build b/target/sparc/meson.build
index d32e67b..48025cc 100644
--- a/target/sparc/meson.build
+++ b/target/sparc/meson.build
@@ -20,4 +20,4 @@ sparc_system_ss.add(files(
))
target_arch += {'sparc': sparc_ss}
-target_softmmu_arch += {'sparc': sparc_system_ss}
+target_system_arch += {'sparc': sparc_system_ss}
diff --git a/target/tricore/meson.build b/target/tricore/meson.build
index 34825b6..45f49f0 100644
--- a/target/tricore/meson.build
+++ b/target/tricore/meson.build
@@ -12,4 +12,4 @@ tricore_ss.add(zlib)
tricore_system_ss = ss.source_set()
target_arch += {'tricore': tricore_ss}
-target_softmmu_arch += {'tricore': tricore_system_ss}
+target_system_arch += {'tricore': tricore_system_ss}
diff --git a/target/xtensa/meson.build b/target/xtensa/meson.build
index 95692bd..f8d6010 100644
--- a/target/xtensa/meson.build
+++ b/target/xtensa/meson.build
@@ -24,4 +24,4 @@ xtensa_system_ss.add(files(
))
target_arch += {'xtensa': xtensa_ss}
-target_softmmu_arch += {'xtensa': xtensa_system_ss}
+target_system_arch += {'xtensa': xtensa_system_ss}
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 69f2daf..3afb896 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -1643,8 +1643,8 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
#define MIN_TLB_MASK_TABLE_OFS -512
/*
- * For softmmu, perform the TLB load and compare.
- * For useronly, perform any required alignment tests.
+ * For system-mode, perform the TLB load and compare.
+ * For user-mode, perform any required alignment tests.
* In both cases, return a TCGLabelQemuLdst structure if the slow path
* is required and fill in @h with the host address for the fast path.
*/
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index a2f6010..0d9c2d1 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -353,7 +353,7 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
#define ALL_VECTOR_REGS 0xffff0000u
/*
- * r0-r3 will be overwritten when reading the tlb entry (softmmu only);
+ * r0-r3 will be overwritten when reading the tlb entry (system-mode only);
* r14 will be overwritten by the BLNE branching to the slow path.
*/
#ifdef CONFIG_SOFTMMU
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 4e47151..788d608 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -2276,7 +2276,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
int movop = OPC_MOVL_EvGv;
/*
- * Do big-endian stores with movbe or softmmu.
+ * Do big-endian stores with movbe or system-mode.
* User-only without movbe will have its swapping done generically.
*/
if (memop & MO_BSWAP) {
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 8f70910..801302d 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -891,8 +891,8 @@ bool tcg_target_has_memory_bswap(MemOp memop)
#define MIN_TLB_MASK_TABLE_OFS -(1 << 11)
/*
- * For softmmu, perform the TLB load and compare.
- * For useronly, perform any required alignment tests.
+ * For system-mode, perform the TLB load and compare.
+ * For user-mode, perform any required alignment tests.
* In both cases, return a TCGLabelQemuLdst structure if the slow path
* is required and fill in @h with the host address for the fast path.
*/
diff --git a/tcg/meson.build b/tcg/meson.build
index 4be4a61..895a11d 100644
--- a/tcg/meson.build
+++ b/tcg/meson.build
@@ -34,12 +34,12 @@ tcg_user = declare_dependency(link_with: libtcg_user,
dependencies: tcg_ss.dependencies())
user_ss.add(tcg_user)
-libtcg_softmmu = static_library('tcg_softmmu',
+libtcg_system = static_library('tcg_system',
tcg_ss.sources() + genh,
name_suffix: 'fa',
c_args: '-DCONFIG_SOFTMMU',
build_by_default: false)
-tcg_softmmu = declare_dependency(link_with: libtcg_softmmu,
+tcg_system = declare_dependency(link_with: libtcg_system,
dependencies: tcg_ss.dependencies())
-system_ss.add(tcg_softmmu)
+system_ss.add(tcg_system)
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index f52bda4..e2892ed 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -1258,8 +1258,8 @@ bool tcg_target_has_memory_bswap(MemOp memop)
#define MIN_TLB_MASK_TABLE_OFS -32768
/*
- * For softmmu, perform the TLB load and compare.
- * For useronly, perform any required alignment tests.
+ * For system-mode, perform the TLB load and compare.
+ * For user-mode, perform any required alignment tests.
* In both cases, return a TCGLabelQemuLdst structure if the slow path
* is required and fill in @h with the host address for the fast path.
*/
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 90d76c2..5c873b2 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -2091,8 +2091,8 @@ bool tcg_target_has_memory_bswap(MemOp memop)
#define MIN_TLB_MASK_TABLE_OFS -32768
/*
- * For softmmu, perform the TLB load and compare.
- * For useronly, perform any required alignment tests.
+ * For system-mode, perform the TLB load and compare.
+ * For user-mode, perform any required alignment tests.
* In both cases, return a TCGLabelQemuLdst structure if the slow path
* is required and fill in @h with the host address for the fast path.
*/
diff --git a/tcg/region.c b/tcg/region.c
index a078899..8669245 100644
--- a/tcg/region.c
+++ b/tcg/region.c
@@ -733,7 +733,7 @@ static int alloc_code_gen_buffer(size_t size, int splitwx, Error **errp)
* and then assigning regions to TCG threads so that the threads can translate
* code in parallel without synchronization.
*
- * In softmmu the number of TCG threads is bounded by max_cpus, so we use at
+ * In system-mode the number of TCG threads is bounded by max_cpus, so we use at
* least max_cpus regions in MTTCG. In !MTTCG we use a single region.
* Note that the TCG options from the command-line (i.e. -accel accel=tcg,[...])
* must have been parsed before calling this function, since it calls
@@ -749,7 +749,7 @@ static int alloc_code_gen_buffer(size_t size, int splitwx, Error **errp)
*
* However, this user-mode limitation is unlikely to be a significant problem
* in practice. Multi-threaded guests share most if not all of their translated
- * code, which makes parallel code generation less appealing than in softmmu.
+ * code, which makes parallel code generation less appealing than in system-mode
*/
void tcg_region_init(size_t tb_size, int splitwx, unsigned max_cpus)
{
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index c2bcdea..d6dbcaf 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -1227,8 +1227,8 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
#define MIN_TLB_MASK_TABLE_OFS -(1 << 11)
/*
- * For softmmu, perform the TLB load and compare.
- * For useronly, perform any required alignment tests.
+ * For system-mode, perform the TLB load and compare.
+ * For user-mode, perform any required alignment tests.
* In both cases, return a TCGLabelQemuLdst structure if the slow path
* is required and fill in @h with the host address for the fast path.
*/
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
index 7552f63..4ef9ac3 100644
--- a/tcg/s390x/tcg-target.c.inc
+++ b/tcg/s390x/tcg-target.c.inc
@@ -1750,8 +1750,8 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
#define MIN_TLB_MASK_TABLE_OFS -(1 << 19)
/*
- * For softmmu, perform the TLB load and compare.
- * For useronly, perform any required alignment tests.
+ * For system-mode, perform the TLB load and compare.
+ * For user-mode, perform any required alignment tests.
* In both cases, return a TCGLabelQemuLdst structure if the slow path
* is required and fill in @h with the host address for the fast path.
*/
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
index 01ac26c..19d9df4 100644
--- a/tcg/sparc64/tcg-target.c.inc
+++ b/tcg/sparc64/tcg-target.c.inc
@@ -1033,8 +1033,8 @@ bool tcg_target_has_memory_bswap(MemOp memop)
#define MIN_TLB_MASK_TABLE_OFS -(1 << 12)
/*
- * For softmmu, perform the TLB load and compare.
- * For useronly, perform any required alignment tests.
+ * For system-mode, perform the TLB load and compare.
+ * For user-mode, perform any required alignment tests.
* In both cases, return a TCGLabelQemuLdst structure if the slow path
* is required and fill in @h with the host address for the fast path.
*/
diff --git a/tcg/tcg.c b/tcg/tcg.c
index f664cf1..637b9e6 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -760,12 +760,13 @@ static void alloc_tcg_plugin_context(TCGContext *s)
* In user-mode we just point tcg_ctx to tcg_init_ctx. See the documentation
* of tcg_region_init() for the reasoning behind this.
*
- * In softmmu each caller registers its context in tcg_ctxs[]. Note that in
- * softmmu tcg_ctxs[] does not track tcg_ctx_init, since the initial context
+ * In system-mode each caller registers its context in tcg_ctxs[]. Note that in
+ * system-mode tcg_ctxs[] does not track tcg_ctx_init, since the initial context
* is not used anymore for translation once this function is called.
*
- * Not tracking tcg_init_ctx in tcg_ctxs[] in softmmu keeps code that iterates
- * over the array (e.g. tcg_code_size() the same for both softmmu and user-mode.
+ * Not tracking tcg_init_ctx in tcg_ctxs[] in system-mode keeps code that
+ * iterates over the array (e.g. tcg_code_size() the same for both system/user
+ * modes.
*/
#ifdef CONFIG_USER_ONLY
void tcg_register_thread(void)
@@ -1349,7 +1350,7 @@ static void tcg_context_init(unsigned max_cpus)
* In user-mode we simply share the init context among threads, since we
* use a single region. See the documentation tcg_region_init() for the
* reasoning behind this.
- * In softmmu we will have at most max_cpus TCG threads.
+ * In system-mode we will have at most max_cpus TCG threads.
*/
#ifdef CONFIG_USER_ONLY
tcg_ctxs = &tcg_ctx;
diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out
index 86a3701..e5e7f42 100644
--- a/tests/qemu-iotests/223.out
+++ b/tests/qemu-iotests/223.out
@@ -83,29 +83,32 @@ exports available: 0
exports available: 3
export: 'n'
size: 4194304
- flags: 0x58f ( readonly flush fua df multi cache )
+ flags: 0x158f ( readonly flush fua df multi cache block-status-payload )
min block: 1
opt block: 4096
max block: 33554432
+ transaction size: 64-bit
available meta contexts: 2
base:allocation
qemu:dirty-bitmap:b
export: 'n2'
description: some text
size: 4194304
- flags: 0xded ( flush fua trim zeroes df multi cache fast-zero )
+ flags: 0x1ded ( flush fua trim zeroes df multi cache fast-zero block-status-payload )
min block: 1
opt block: 4096
max block: 33554432
+ transaction size: 64-bit
available meta contexts: 2
base:allocation
qemu:dirty-bitmap:b2
export: 'n3'
size: 4194304
- flags: 0x58f ( readonly flush fua df multi cache )
+ flags: 0x158f ( readonly flush fua df multi cache block-status-payload )
min block: 1
opt block: 4096
max block: 33554432
+ transaction size: 64-bit
available meta contexts: 2
base:allocation
qemu:dirty-bitmap:b3
@@ -202,29 +205,32 @@ exports available: 0
exports available: 3
export: 'n'
size: 4194304
- flags: 0x58f ( readonly flush fua df multi cache )
+ flags: 0x158f ( readonly flush fua df multi cache block-status-payload )
min block: 1
opt block: 4096
max block: 33554432
+ transaction size: 64-bit
available meta contexts: 2
base:allocation
qemu:dirty-bitmap:b
export: 'n2'
description: some text
size: 4194304
- flags: 0xded ( flush fua trim zeroes df multi cache fast-zero )
+ flags: 0x1ded ( flush fua trim zeroes df multi cache fast-zero block-status-payload )
min block: 1
opt block: 4096
max block: 33554432
+ transaction size: 64-bit
available meta contexts: 2
base:allocation
qemu:dirty-bitmap:b2
export: 'n3'
size: 4194304
- flags: 0x58f ( readonly flush fua df multi cache )
+ flags: 0x158f ( readonly flush fua df multi cache block-status-payload )
min block: 1
opt block: 4096
max block: 33554432
+ transaction size: 64-bit
available meta contexts: 2
base:allocation
qemu:dirty-bitmap:b3
diff --git a/tests/qemu-iotests/233.out b/tests/qemu-iotests/233.out
index 237c827..1910f7d 100644
--- a/tests/qemu-iotests/233.out
+++ b/tests/qemu-iotests/233.out
@@ -39,6 +39,7 @@ exports available: 1
export: ''
size: 67108864
min block: 1
+ transaction size: 64-bit
== check TLS fail over TCP with mismatched hostname ==
qemu-img: Could not open 'driver=nbd,host=localhost,port=PORT,tls-creds=tls0': Certificate does not match the hostname localhost
@@ -53,6 +54,7 @@ exports available: 1
export: ''
size: 67108864
min block: 1
+ transaction size: 64-bit
== check TLS with different CA fails ==
qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': The certificate hasn't got a known issuer
@@ -83,6 +85,7 @@ exports available: 1
export: ''
size: 67108864
min block: 1
+ transaction size: 64-bit
== check TLS works over UNIX with PSK ==
image: nbd+unix://?socket=SOCK_DIR/qemu-nbd.sock
@@ -93,6 +96,7 @@ exports available: 1
export: ''
size: 67108864
min block: 1
+ transaction size: 64-bit
== check TLS fails over UNIX with mismatch PSK ==
qemu-img: Could not open 'driver=nbd,path=SOCK_DIR/qemu-nbd.sock,tls-creds=tls0': TLS handshake failed: The TLS connection was non-properly terminated.
diff --git a/tests/qemu-iotests/241.out b/tests/qemu-iotests/241.out
index 7946c28..7267cd2 100644
--- a/tests/qemu-iotests/241.out
+++ b/tests/qemu-iotests/241.out
@@ -6,6 +6,7 @@ exports available: 1
export: ''
size: 1024
min block: 1
+ transaction size: 64-bit
[{ "start": 0, "length": 1000, "depth": 0, "present": true, "zero": false, "data": true, "compressed": false, "offset": OFFSET},
{ "start": 1000, "length": 24, "depth": 0, "present": true, "zero": true, "data": false, "compressed": false, "offset": OFFSET}]
1 KiB (0x400) bytes allocated at offset 0 bytes (0x0)
@@ -16,6 +17,7 @@ exports available: 1
export: ''
size: 1024
min block: 512
+ transaction size: 64-bit
[{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "compressed": false, "offset": OFFSET}]
1 KiB (0x400) bytes allocated at offset 0 bytes (0x0)
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
@@ -28,6 +30,7 @@ exports available: 1
export: ''
size: 1024
min block: 1
+ transaction size: 64-bit
[{ "start": 0, "length": 1000, "depth": 0, "present": true, "zero": false, "data": true, "compressed": false, "offset": OFFSET},
{ "start": 1000, "length": 24, "depth": 0, "present": true, "zero": true, "data": false, "compressed": false, "offset": OFFSET}]
1 KiB (0x400) bytes allocated at offset 0 bytes (0x0)
diff --git a/tests/qemu-iotests/307.out b/tests/qemu-iotests/307.out
index 390f05d..f645f33 100644
--- a/tests/qemu-iotests/307.out
+++ b/tests/qemu-iotests/307.out
@@ -15,10 +15,11 @@ wrote 4096/4096 bytes at offset 0
exports available: 1
export: 'fmt'
size: 67108864
- flags: 0x58f ( readonly flush fua df multi cache )
+ flags: 0x158f ( readonly flush fua df multi cache block-status-payload )
min block: XXX
opt block: XXX
max block: XXX
+ transaction size: 64-bit
available meta contexts: 1
base:allocation
@@ -43,10 +44,11 @@ exports available: 1
exports available: 1
export: 'fmt'
size: 67108864
- flags: 0x58f ( readonly flush fua df multi cache )
+ flags: 0x158f ( readonly flush fua df multi cache block-status-payload )
min block: XXX
opt block: XXX
max block: XXX
+ transaction size: 64-bit
available meta contexts: 1
base:allocation
@@ -74,19 +76,21 @@ exports available: 1
exports available: 2
export: 'fmt'
size: 67108864
- flags: 0x58f ( readonly flush fua df multi cache )
+ flags: 0x158f ( readonly flush fua df multi cache block-status-payload )
min block: XXX
opt block: XXX
max block: XXX
+ transaction size: 64-bit
available meta contexts: 1
base:allocation
export: 'export1'
description: This is the writable second export
size: 67108864
- flags: 0xded ( flush fua trim zeroes df multi cache fast-zero )
+ flags: 0x1ded ( flush fua trim zeroes df multi cache fast-zero block-status-payload )
min block: XXX
opt block: XXX
max block: XXX
+ transaction size: 64-bit
available meta contexts: 1
base:allocation
@@ -109,10 +113,11 @@ exports available: 1
export: 'export1'
description: This is the writable second export
size: 67108864
- flags: 0xded ( flush fua trim zeroes df multi cache fast-zero )
+ flags: 0x1ded ( flush fua trim zeroes df multi cache fast-zero block-status-payload )
min block: XXX
opt block: XXX
max block: XXX
+ transaction size: 64-bit
available meta contexts: 1
base:allocation
diff --git a/tests/qemu-iotests/tests/nbd-qemu-allocation.out b/tests/qemu-iotests/tests/nbd-qemu-allocation.out
index 138eb09..56b57c6 100644
--- a/tests/qemu-iotests/tests/nbd-qemu-allocation.out
+++ b/tests/qemu-iotests/tests/nbd-qemu-allocation.out
@@ -17,10 +17,11 @@ wrote 2097152/2097152 bytes at offset 1048576
exports available: 1
export: ''
size: 4194304
- flags: 0x48f ( readonly flush fua df cache )
+ flags: 0x148f ( readonly flush fua df cache block-status-payload )
min block: 1
opt block: 4096
max block: 33554432
+ transaction size: 64-bit
available meta contexts: 2
base:allocation
qemu:allocation-depth
diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c
index 3bedb81..9b9c9f9 100644
--- a/tests/qtest/fuzz/fuzz.c
+++ b/tests/qtest/fuzz/fuzz.c
@@ -207,7 +207,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
fuzz_target->pre_vm_init();
}
- /* Run QEMU's softmmu main with the fuzz-target dependent arguments */
+ /* Run QEMU's system main with the fuzz-target dependent arguments */
cmd_line = fuzz_target->get_init_cmdline(fuzz_target);
g_string_append_printf(cmd_line, " %s -qtest /dev/null ",
getenv("QTEST_LOG") ? "" : "-qtest-log none");
diff --git a/tests/qtest/fuzz/fuzz.h b/tests/qtest/fuzz/fuzz.h
index 21d1362..7da0bc3 100644
--- a/tests/qtest/fuzz/fuzz.h
+++ b/tests/qtest/fuzz/fuzz.h
@@ -49,13 +49,13 @@ typedef struct FuzzTarget {
/*
- * Returns the arguments that are passed to qemu/softmmu init(). Freed by
+ * Returns the arguments that are passed to qemu/system init(). Freed by
* the caller.
*/
GString *(*get_init_cmdline)(struct FuzzTarget *);
/*
- * will run once, prior to running qemu/softmmu init.
+ * will run once, prior to running qemu/system init.
* eg: set up shared-memory for communication with the child-process
* Can be NULL
*/
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index b1eba71..3f94a4f 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -421,9 +421,6 @@ static QTestState *G_GNUC_PRINTF(1, 2) qtest_spawn_qemu(const char *fmt, ...)
int sig = SIGKILL;
procctl(P_PID, getpid(), PROC_PDEATHSIG_CTL, &sig);
#endif /* __FreeBSD__ */
- if (!g_setenv("QEMU_AUDIO_DRV", "none", true)) {
- exit(1);
- }
execlp("/bin/sh", "sh", "-c", command->str, NULL);
exit(1);
}
@@ -464,6 +461,7 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
"-chardev socket,path=%s,id=char0 "
"-mon chardev=char0,mode=control "
"-display none "
+ "-audio none "
"%s"
" -accel qtest",
socket_path,
diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target
index 462289f..f3a189c 100644
--- a/tests/tcg/Makefile.target
+++ b/tests/tcg/Makefile.target
@@ -120,7 +120,7 @@ endif
%: %.S
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
else
-# For softmmu targets we include a different Makefile fragment as the
+# For system targets we include a different Makefile fragment as the
# build options for bare programs are usually pretty different. They
# are expected to provide their own build recipes.
EXTRA_CFLAGS += -ffreestanding
diff --git a/tests/tcg/multiarch/gdbstub/interrupt.py b/tests/tcg/multiarch/gdbstub/interrupt.py
index e222ac9..c016e7a 100644
--- a/tests/tcg/multiarch/gdbstub/interrupt.py
+++ b/tests/tcg/multiarch/gdbstub/interrupt.py
@@ -1,6 +1,6 @@
from __future__ import print_function
#
-# Test some of the softmmu debug features with the multiarch memory
+# Test some of the system debug features with the multiarch memory
# test. It is a port of the original vmlinux focused test case but
# using the "memory" test instead.
#
diff --git a/tests/tcg/multiarch/gdbstub/memory.py b/tests/tcg/multiarch/gdbstub/memory.py
index dd25e72..fb1d06b 100644
--- a/tests/tcg/multiarch/gdbstub/memory.py
+++ b/tests/tcg/multiarch/gdbstub/memory.py
@@ -1,6 +1,6 @@
from __future__ import print_function
#
-# Test some of the softmmu debug features with the multiarch memory
+# Test some of the system debug features with the multiarch memory
# test. It is a port of the original vmlinux focused test case but
# using the "memory" test instead.
#
diff --git a/tests/tcg/multiarch/system/memory.c b/tests/tcg/multiarch/system/memory.c
index e29786a..6eb2eb1 100644
--- a/tests/tcg/multiarch/system/memory.c
+++ b/tests/tcg/multiarch/system/memory.c
@@ -1,14 +1,14 @@
/*
* Memory Test
*
- * This is intended to test the softmmu code and ensure we properly
+ * This is intended to test the system-mode code and ensure we properly
* behave across normal and unaligned accesses across several pages.
* We are not replicating memory tests for stuck bits and other
* hardware level failures but looking for issues with different size
* accesses when access is:
*
* - unaligned at various sizes (if -DCHECK_UNALIGNED set)
- * - spanning a (softmmu) page
+ * - spanning a (system) page
* - sign extension when loading
*/
diff --git a/tests/tcg/s390x/pgm-specification-softmmu.S b/tests/tcg/s390x/pgm-specification-softmmu.S
index d534f4e..86c340a 100644
--- a/tests/tcg/s390x/pgm-specification-softmmu.S
+++ b/tests/tcg/s390x/pgm-specification-softmmu.S
@@ -1,5 +1,5 @@
/*
- * Common softmmu code for specification exception testing.
+ * Common system code for specification exception testing.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
diff --git a/tests/tcg/s390x/pgm-specification.mak b/tests/tcg/s390x/pgm-specification.mak
index 2999aee..73dc47a 100644
--- a/tests/tcg/s390x/pgm-specification.mak
+++ b/tests/tcg/s390x/pgm-specification.mak
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# List of specification exception tests.
-# Shared between the softmmu and the user makefiles.
+# Shared between the system and the user makefiles.
PGM_SPECIFICATION_TESTS = \
br-odd \
cgrl-unaligned \
diff --git a/tests/tcg/s390x/softmmu.ld b/tests/tcg/s390x/softmmu.ld
index ea944ea..c7a8864 100644
--- a/tests/tcg/s390x/softmmu.ld
+++ b/tests/tcg/s390x/softmmu.ld
@@ -1,5 +1,5 @@
/*
- * Linker script for the softmmu test kernels.
+ * Linker script for the system test kernels.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
diff --git a/tests/tcg/xtensa/Makefile.softmmu-target b/tests/tcg/xtensa/Makefile.softmmu-target
index 78bf72d..a29571b 100644
--- a/tests/tcg/xtensa/Makefile.softmmu-target
+++ b/tests/tcg/xtensa/Makefile.softmmu-target
@@ -1,5 +1,5 @@
#
-# Xtensa softmmu tests
+# Xtensa system tests
#
CORE=dc232b
diff --git a/tests/tcg/xtensaeb/Makefile.softmmu-target b/tests/tcg/xtensaeb/Makefile.softmmu-target
index 4204a96..95d0528 100644
--- a/tests/tcg/xtensaeb/Makefile.softmmu-target
+++ b/tests/tcg/xtensaeb/Makefile.softmmu-target
@@ -1,5 +1,5 @@
#
-# Xtensa softmmu tests
+# Xtensa system tests
#
include $(SRC_PATH)/tests/tcg/xtensa/Makefile.softmmu-target
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index 1977b30..f33ae64 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -59,7 +59,7 @@ if have_system or have_tools
}
if seccomp.found()
- tests += {'test-seccomp': ['../../softmmu/qemu-seccomp.c', seccomp]}
+ tests += {'test-seccomp': ['../../system/qemu-seccomp.c', seccomp]}
endif
endif
diff --git a/trace/control.c b/trace/control.c
index 1a48a7e..ef10782 100644
--- a/trace/control.c
+++ b/trace/control.c
@@ -285,10 +285,10 @@ bool trace_init_backends(void)
return true;
}
-void trace_opt_parse(const char *optarg)
+void trace_opt_parse(const char *optstr)
{
QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("trace"),
- optarg, true);
+ optstr, true);
if (!opts) {
exit(1);
}
diff --git a/trace/control.h b/trace/control.h
index dfd209e..6754bfe 100644
--- a/trace/control.h
+++ b/trace/control.h
@@ -197,11 +197,11 @@ extern QemuOptsList qemu_trace_opts;
/**
* trace_opt_parse:
- * @optarg: A string argument of --trace command line argument
+ * @optstr: A string argument of --trace command line argument
*
* Initialize tracing subsystem.
*/
-void trace_opt_parse(const char *optarg);
+void trace_opt_parse(const char *optstr);
/**
* trace_get_vcpu_event_count:
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 145f42d..d952760 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -343,9 +343,9 @@ QemuCocoaView *cocoaView;
static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEventRef cgEvent, void *userInfo)
{
- QemuCocoaView *cocoaView = userInfo;
+ QemuCocoaView *view = userInfo;
NSEvent *event = [NSEvent eventWithCGEvent:cgEvent];
- if ([cocoaView isMouseGrabbed] && [cocoaView handleEvent:event]) {
+ if ([view isMouseGrabbed] && [view handleEvent:event]) {
COCOA_DEBUG("Global events tap: qemu handled the event, capturing!\n");
return NULL;
}
diff --git a/ui/vnc.c b/ui/vnc.c
index 6056028..4f23a0f 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -4185,6 +4185,8 @@ void vnc_display_open(const char *id, Error **errp)
if (!vd->audio_state) {
goto fail;
}
+ } else {
+ vd->audio_state = audio_get_default_audio_state(NULL);
}
device_id = qemu_opt_get(opts, "display");
diff --git a/util/cutils.c b/util/cutils.c
index 2537319..c99d26c 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -1012,8 +1012,17 @@ int qemu_pstrcmp0(const char **str1, const char **str2)
static inline bool starts_with_prefix(const char *dir)
{
size_t prefix_len = strlen(CONFIG_PREFIX);
+ /*
+ * dir[prefix_len] is only accessed if the length of dir is
+ * >= prefix_len, so no out of bounds access is possible.
+ */
+#pragma GCC diagnostic push
+#if !defined(__clang__) || __has_warning("-Warray-bounds=")
+#pragma GCC diagnostic ignored "-Warray-bounds="
+#endif
return !memcmp(dir, CONFIG_PREFIX, prefix_len) &&
(!dir[prefix_len] || G_IS_DIR_SEPARATOR(dir[prefix_len]));
+#pragma GCC diagnostic pop
}
/* Return the next path component in dir, and store its length in *p_len. */
@@ -1144,7 +1153,6 @@ char *get_relocated_path(const char *dir)
{
size_t prefix_len = strlen(CONFIG_PREFIX);
const char *bindir = CONFIG_BINDIR;
- const char *exec_dir = qemu_get_exec_dir();
GString *result;
int len_dir, len_bindir;
diff --git a/util/guest-random.c b/util/guest-random.c
index 9465dda..33607d5 100644
--- a/util/guest-random.c
+++ b/util/guest-random.c
@@ -87,11 +87,11 @@ void qemu_guest_random_seed_thread_part2(uint64_t seed)
}
}
-int qemu_guest_random_seed_main(const char *optarg, Error **errp)
+int qemu_guest_random_seed_main(const char *seedstr, Error **errp)
{
uint64_t seed;
- if (parse_uint_full(optarg, 0, &seed)) {
- error_setg(errp, "Invalid seed number: %s", optarg);
+ if (parse_uint_full(seedstr, 0, &seed)) {
+ error_setg(errp, "Invalid seed number: %s", seedstr);
return -1;
} else {
deterministic = true;
diff --git a/util/log.c b/util/log.c
index def88a9..d36c98d 100644
--- a/util/log.c
+++ b/util/log.c
@@ -298,6 +298,8 @@ static bool qemu_set_log_internal(const char *filename, bool changed_name,
r->fd = logfile;
qatomic_rcu_set(&global_file, NULL);
call_rcu(r, rcu_close_file, rcu);
+ }
+ if (changed_name) {
logfile = NULL;
}
}