aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS12
-rw-r--r--Makefile11
-rw-r--r--audio/dsoundaudio.c7
-rw-r--r--audio/jackaudio.c4
-rw-r--r--block.c11
-rw-r--r--block/block-backend.c19
-rw-r--r--block/commit.c1
-rw-r--r--block/curl.c11
-rw-r--r--block/export/fuse.c4
-rw-r--r--block/file-posix.c37
-rw-r--r--block/io_uring.c19
-rw-r--r--block/iscsi.c4
-rw-r--r--block/linux-aio.c16
-rw-r--r--block/mirror.c15
-rw-r--r--block/monitor/block-hmp-cmds.c2
-rw-r--r--block/nfs.c6
-rw-r--r--block/nvme.c51
-rw-r--r--block/ssh.c4
-rw-r--r--block/vvfat.c37
-rw-r--r--block/win32-aio.c4
-rw-r--r--blockdev.c24
-rw-r--r--bsd-user/include/special-errno.h (renamed from bsd-user/special-errno.h)0
-rw-r--r--bsd-user/meson.build2
-rw-r--r--common-user/meson.build2
-rw-r--r--configs/devices/mips-softmmu/common.mak2
-rwxr-xr-xconfigure189
-rw-r--r--contrib/elf2dmp/meson.build2
-rw-r--r--contrib/ivshmem-client/meson.build2
-rw-r--r--contrib/ivshmem-server/meson.build2
-rw-r--r--contrib/rdmacm-mux/meson.build2
-rw-r--r--docs/papr-pef.txt30
-rw-r--r--docs/specs/ppc-spapr-hcalls.rst21
-rw-r--r--docs/system/ppc/pseries.rst75
-rw-r--r--docs/tools/qemu-storage-daemon.rst2
-rw-r--r--hw/audio/intel-hda.c2
-rw-r--r--hw/block/block.c3
-rw-r--r--hw/block/dataplane/virtio-blk.c16
-rw-r--r--hw/block/virtio-blk.c14
-rw-r--r--hw/display/Kconfig2
-rw-r--r--hw/display/edid-generate.c7
-rw-r--r--hw/display/macfb.c2
-rw-r--r--hw/display/meson.build2
-rw-r--r--hw/display/vga-isa-mm.c114
-rw-r--r--hw/display/vga-mmio.c139
-rw-r--r--hw/display/vhost-user-gpu.c6
-rw-r--r--hw/input/ps2.c57
-rw-r--r--hw/m68k/q800.c5
-rw-r--r--hw/m68k/virt.c9
-rw-r--r--hw/mips/Kconfig2
-rw-r--r--hw/mips/jazz.c9
-rw-r--r--hw/net/vhost_net-stub.c9
-rw-r--r--hw/net/vhost_net.c9
-rw-r--r--hw/net/virtio-net.c10
-rw-r--r--hw/pci-host/pnv_phb3.c57
-rw-r--r--hw/pci-host/pnv_phb4.c486
-rw-r--r--hw/pci-host/pnv_phb4_pec.c347
-rw-r--r--hw/ppc/pnv.c55
-rw-r--r--hw/ppc/spapr.c10
-rw-r--r--hw/scsi/virtio-scsi-dataplane.c60
-rw-r--r--hw/scsi/virtio-scsi.c2
-rw-r--r--hw/sd/sd.c52
-rw-r--r--hw/usb/desc.c15
-rw-r--r--hw/usb/desc.h1
-rw-r--r--hw/usb/dev-uas.c1
-rw-r--r--hw/usb/dev-wacom.c72
-rw-r--r--hw/virtio/trace-events1
-rw-r--r--hw/virtio/vhost-user-fs.c6
-rw-r--r--hw/virtio/vhost-vdpa.c7
-rw-r--r--hw/virtio/vhost-vsock-common.c6
-rw-r--r--hw/virtio/vhost.c76
-rw-r--r--hw/virtio/virtio-crypto.c6
-rw-r--r--hw/virtio/virtio-mmio.c27
-rw-r--r--hw/virtio/virtio-pci.c269
-rw-r--r--hw/virtio/virtio-pci.h4
-rw-r--r--hw/virtio/virtio.c102
-rw-r--r--hw/xen/xen-bus.c6
-rw-r--r--include/block/aio.h4
-rw-r--r--include/block/block.h9
-rw-r--r--include/block/block_int.h3
-rw-r--r--include/hw/display/vga.h6
-rw-r--r--include/hw/pci-host/pnv_phb3.h4
-rw-r--r--include/hw/pci-host/pnv_phb4.h14
-rw-r--r--include/hw/ppc/pnv.h8
-rw-r--r--include/hw/virtio/vhost-backend.h3
-rw-r--r--include/hw/virtio/vhost.h4
-rw-r--r--include/hw/virtio/virtio-blk.h2
-rw-r--r--include/hw/virtio/virtio-gpu.h4
-rw-r--r--include/hw/virtio/virtio.h12
-rw-r--r--include/net/vhost_net.h2
-rw-r--r--include/sysemu/blockdev.h3
-rw-r--r--io/channel-command.c6
-rw-r--r--io/channel-file.c3
-rw-r--r--io/channel-socket.c3
-rw-r--r--linux-user/aarch64/target_structs.h59
-rw-r--r--linux-user/alpha/cpu_loop.c61
-rw-r--r--linux-user/arm/target_structs.h60
-rw-r--r--linux-user/cris/cpu_loop.c12
-rw-r--r--linux-user/cris/target_structs.h59
-rw-r--r--linux-user/elfload.c2
-rw-r--r--linux-user/generic/target_structs.h58
-rw-r--r--linux-user/hexagon/target_structs.h55
-rw-r--r--linux-user/hppa/cpu_loop.c26
-rw-r--r--linux-user/i386/cpu_loop.c78
-rw-r--r--linux-user/i386/target_structs.h59
-rw-r--r--linux-user/include/host/aarch64/host-signal.h (renamed from linux-user/host/aarch64/host-signal.h)0
-rw-r--r--linux-user/include/host/alpha/host-signal.h (renamed from linux-user/host/alpha/host-signal.h)0
-rw-r--r--linux-user/include/host/arm/host-signal.h (renamed from linux-user/host/arm/host-signal.h)0
-rw-r--r--linux-user/include/host/i386/host-signal.h (renamed from linux-user/host/i386/host-signal.h)0
-rw-r--r--linux-user/include/host/loongarch64/host-signal.h (renamed from linux-user/host/loongarch64/host-signal.h)0
-rw-r--r--linux-user/include/host/mips/host-signal.h (renamed from linux-user/host/mips/host-signal.h)0
-rw-r--r--linux-user/include/host/ppc/host-signal.h (renamed from linux-user/host/ppc/host-signal.h)0
-rw-r--r--linux-user/include/host/ppc64/host-signal.h (renamed from linux-user/host/ppc64/host-signal.h)0
-rw-r--r--linux-user/include/host/riscv/host-signal.h (renamed from linux-user/host/riscv/host-signal.h)0
-rw-r--r--linux-user/include/host/s390/host-signal.h (renamed from linux-user/host/s390/host-signal.h)0
-rw-r--r--linux-user/include/host/s390x/host-signal.h (renamed from linux-user/host/s390x/host-signal.h)0
-rw-r--r--linux-user/include/host/sparc/host-signal.h (renamed from linux-user/host/sparc/host-signal.h)0
-rw-r--r--linux-user/include/host/sparc64/host-signal.h (renamed from linux-user/host/sparc64/host-signal.h)0
-rw-r--r--linux-user/include/host/x32/host-signal.h (renamed from linux-user/host/x32/host-signal.h)0
-rw-r--r--linux-user/include/host/x86_64/host-signal.h (renamed from linux-user/host/x86_64/host-signal.h)0
-rw-r--r--linux-user/include/special-errno.h (renamed from linux-user/special-errno.h)0
-rw-r--r--linux-user/m68k/cpu_loop.c24
-rw-r--r--linux-user/m68k/target_structs.h59
-rw-r--r--linux-user/meson.build4
-rw-r--r--linux-user/microblaze/cpu_loop.c71
-rw-r--r--linux-user/microblaze/target_structs.h59
-rw-r--r--linux-user/mips/cpu_loop.c166
-rw-r--r--linux-user/nios2/target_structs.h59
-rw-r--r--linux-user/openrisc/cpu_loop.c18
-rw-r--r--linux-user/openrisc/target_structs.h59
-rw-r--r--linux-user/ppc/cpu_loop.c136
-rw-r--r--linux-user/riscv/cpu_loop.c31
-rw-r--r--linux-user/riscv/target_structs.h47
-rw-r--r--linux-user/s390x/cpu_loop.c7
-rw-r--r--linux-user/sh4/cpu_loop.c6
-rw-r--r--linux-user/sh4/target_structs.h59
-rw-r--r--linux-user/sparc/cpu_loop.c14
-rw-r--r--linux-user/syscall.c19
-rw-r--r--linux-user/syscall_defs.h3
-rw-r--r--linux-user/x86_64/target_structs.h36
-rw-r--r--linux-user/xtensa/cpu_loop.c26
-rw-r--r--meson.build37
-rw-r--r--migration/rdma.c8
-rw-r--r--pc-bios/README2
-rw-r--r--pc-bios/s390-ccw/Makefile2
-rw-r--r--pc-bios/slof.binbin991920 -> 992384 bytes
-rw-r--r--plugins/meson.build13
-rw-r--r--python/qemu/aqmp/aqmp_tui.py3
-rw-r--r--python/qemu/aqmp/protocol.py5
-rw-r--r--python/qemu/qmp/qom_common.py6
-rw-r--r--qapi/block-core.json7
-rw-r--r--qapi/block-export.json6
-rw-r--r--qapi/qdev.json5
-rw-r--r--qapi/ui.json2
-rw-r--r--qemu-edid.c4
-rw-r--r--qemu-img.c23
m---------roms/SLOF0
-rwxr-xr-xscripts/ci/org.centos/stream/8/x86_64/configure1
-rwxr-xr-xscripts/coverity-scan/run-coverity-scan2
-rwxr-xr-xscripts/make-config-poison.sh16
-rwxr-xr-xscripts/meson-buildoptions.py21
-rw-r--r--scripts/meson-buildoptions.sh3
-rwxr-xr-xscripts/render_block_graph.py1
-rw-r--r--scripts/simplebench/bench-example.py2
-rw-r--r--softmmu/vl.c8
-rw-r--r--storage-daemon/qemu-storage-daemon.c13
-rw-r--r--target/i386/cpu.h3
-rw-r--r--target/i386/kvm/kvm.c130
-rw-r--r--target/i386/machine.c29
-rw-r--r--target/m68k/op_helper.c5
-rw-r--r--target/mips/tcg/micromips_translate.c.inc10
-rw-r--r--target/mips/tcg/mips16e_translate.c.inc2
-rw-r--r--target/mips/tcg/nanomips_translate.c.inc4
-rw-r--r--target/mips/tcg/translate.c36
-rw-r--r--target/mips/tcg/translate.h1
-rw-r--r--target/ppc/arch_dump.c2
-rw-r--r--target/ppc/cpu.h25
-rw-r--r--target/ppc/cpu_init.c2
-rw-r--r--target/ppc/excp_helper.c185
-rwxr-xr-xtests/qemu-iotests/1221
-rw-r--r--tests/qemu-iotests/122.out2
-rw-r--r--tests/qemu-iotests/273.out4
-rwxr-xr-xtests/qemu-iotests/30825
-rw-r--r--tests/qemu-iotests/308.out2
-rw-r--r--tests/qemu-iotests/testrunner.py21
-rwxr-xr-xtests/qemu-iotests/tests/stream-error-on-reset140
-rw-r--r--tests/qemu-iotests/tests/stream-error-on-reset.out5
-rw-r--r--tests/qtest/device-plug-test.c19
-rw-r--r--tests/qtest/meson.build3
-rw-r--r--tests/tcg/Makefile.target2
-rw-r--r--tests/unit/meson.build2
-rw-r--r--tests/unit/test-aio.c4
-rw-r--r--tests/unit/test-fdmon-epoll.c4
-rw-r--r--ui/cocoa.m18
-rw-r--r--ui/dbus.c1
-rw-r--r--ui/gtk-clipboard.c21
-rw-r--r--ui/gtk.c54
-rw-r--r--ui/input-legacy.c15
-rw-r--r--ui/sdl2.c5
-rw-r--r--ui/vnc.c4
-rw-r--r--util/aio-posix.c89
-rw-r--r--util/aio-posix.h1
-rw-r--r--util/aio-win32.c4
-rw-r--r--util/async.c10
-rw-r--r--util/main-loop.c4
-rw-r--r--util/meson.build7
-rw-r--r--util/qemu-coroutine-io.c5
-rw-r--r--util/vhost-user-server.c11
207 files changed, 2384 insertions, 2960 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 391904bc60..2fd74c4642 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1245,7 +1245,7 @@ F: hw/openrisc/openrisc_sim.c
PowerPC Machines
----------------
-405
+405 (ref405ep and taihu)
L: qemu-ppc@nongnu.org
S: Orphan
F: hw/ppc/ppc405_boards.c
@@ -1281,6 +1281,7 @@ New World (mac99)
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
L: qemu-ppc@nongnu.org
S: Odd Fixes
+F: docs/system/ppc/powermac.rst
F: hw/ppc/mac_newworld.c
F: hw/pci-host/uninorth.c
F: hw/pci-bridge/dec.[hc]
@@ -1299,6 +1300,7 @@ Old World (g3beige)
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
L: qemu-ppc@nongnu.org
S: Odd Fixes
+F: docs/system/ppc/powermac.rst
F: hw/ppc/mac_oldworld.c
F: hw/pci-host/grackle.c
F: hw/misc/macio/
@@ -1312,6 +1314,7 @@ PReP
M: Hervé Poussineau <hpoussin@reactos.org>
L: qemu-ppc@nongnu.org
S: Maintained
+F: docs/system/ppc/prep.rst
F: hw/ppc/prep.c
F: hw/ppc/prep_systemio.c
F: hw/ppc/rs6000_mc.c
@@ -1324,7 +1327,7 @@ F: include/hw/isa/pc87312.h
F: include/hw/rtc/m48t59.h
F: tests/avocado/ppc_prep_40p.py
-sPAPR
+sPAPR (pseries)
M: Cédric Le Goater <clg@kaod.org>
M: Daniel Henrique Barboza <danielhb413@gmail.com>
R: David Gibson <david@gibson.dropbear.id.au>
@@ -1336,8 +1339,8 @@ F: include/hw/*/spapr*
F: hw/*/xics*
F: include/hw/*/xics*
F: pc-bios/slof.bin
-F: docs/specs/ppc-spapr-hcalls.txt
-F: docs/specs/ppc-spapr-hotplug.txt
+F: docs/system/ppc/pseries.rst
+F: docs/specs/ppc-spapr-*
F: tests/qtest/spapr*
F: tests/qtest/libqos/*spapr*
F: tests/qtest/rtas*
@@ -1348,6 +1351,7 @@ PowerNV (Non-Virtualized)
M: Cédric Le Goater <clg@kaod.org>
L: qemu-ppc@nongnu.org
S: Maintained
+F: docs/system/ppc/powernv.rst
F: hw/ppc/pnv*
F: hw/intc/pnv*
F: hw/intc/xics_pnv.c
diff --git a/Makefile b/Makefile
index 5d66c35ea5..9e2e3bf004 100644
--- a/Makefile
+++ b/Makefile
@@ -206,14 +206,11 @@ recurse-clean: $(addsuffix /clean, $(ROM_DIRS))
clean: recurse-clean
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean || :
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) clean-ctlist || :
-# avoid old build problems by removing potentially incorrect old files
- rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
find . \( -name '*.so' -o -name '*.dll' -o -name '*.[oda]' \) -type f \
! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-aarch64.a \
! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-arm.a \
-exec rm {} +
- rm -f TAGS cscope.* *.pod *~ */*~
- rm -f fsdev/*.pod scsi/*.pod
+ rm -f TAGS cscope.* *~ */*~
VERSION = $(shell cat $(SRC_PATH)/VERSION)
@@ -224,10 +221,10 @@ qemu-%.tar.bz2:
distclean: clean
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || :
- rm -f config-host.mak config-host.h* config-poison.h
+ rm -f config-host.mak
rm -f tests/tcg/config-*.mak
- rm -f config-all-disas.mak config.status
- rm -f roms/seabios/config.mak roms/vgabios/config.mak
+ rm -f config.status
+ rm -f roms/seabios/config.mak
rm -f qemu-plugins-ld.symbols qemu-plugins-ld64.symbols
rm -f *-config-target.h *-config-devices.mak *-config-devices.h
rm -rf meson-private meson-logs meson-info compile_commands.json
diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c
index cfc79c129e..3dd2c4d4a6 100644
--- a/audio/dsoundaudio.c
+++ b/audio/dsoundaudio.c
@@ -536,13 +536,12 @@ static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size)
DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
HRESULT hr;
- DWORD cpos, rpos, act_size;
+ DWORD rpos, act_size;
size_t req_size;
int err;
void *ret;
- hr = IDirectSoundCaptureBuffer_GetCurrentPosition(
- dscb, &cpos, ds->first_time ? &rpos : NULL);
+ hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, NULL, &rpos);
if (FAILED(hr)) {
dsound_logerr(hr, "Could not get capture buffer position\n");
*size = 0;
@@ -554,7 +553,7 @@ static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size)
ds->first_time = false;
}
- req_size = audio_ring_dist(cpos, hw->pos_emul, hw->size_emul);
+ req_size = audio_ring_dist(rpos, hw->pos_emul, hw->size_emul);
req_size = MIN(*size, MIN(req_size, hw->size_emul - hw->pos_emul));
if (req_size == 0) {
diff --git a/audio/jackaudio.c b/audio/jackaudio.c
index e7de6d5433..317009e936 100644
--- a/audio/jackaudio.c
+++ b/audio/jackaudio.c
@@ -622,6 +622,7 @@ static void qjack_enable_in(HWVoiceIn *hw, bool enable)
ji->c.enabled = enable;
}
+#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
static int qjack_thread_creator(jack_native_thread_t *thread,
const pthread_attr_t *attr, void *(*function)(void *), void *arg)
{
@@ -635,6 +636,7 @@ static int qjack_thread_creator(jack_native_thread_t *thread,
return ret;
}
+#endif
static void *qjack_init(Audiodev *dev)
{
@@ -687,7 +689,9 @@ static void register_audio_jack(void)
{
qemu_mutex_init(&qjack_shutdown_lock);
audio_driver_register(&jack_driver);
+#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
jack_set_thread_creator(qjack_thread_creator);
+#endif
jack_set_error_function(qjack_error);
jack_set_info_function(qjack_info);
}
diff --git a/block.c b/block.c
index 0ac5b163d2..7b3ce415d8 100644
--- a/block.c
+++ b/block.c
@@ -103,6 +103,8 @@ static int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
static void bdrv_reopen_commit(BDRVReopenState *reopen_state);
static void bdrv_reopen_abort(BDRVReopenState *reopen_state);
+static bool bdrv_backing_overridden(BlockDriverState *bs);
+
/* If non-zero, use only whitelisted block drivers */
static int use_bdrv_whitelist;
@@ -2483,7 +2485,6 @@ char *bdrv_perm_names(uint64_t perm)
{ BLK_PERM_WRITE, "write" },
{ BLK_PERM_WRITE_UNCHANGED, "write unchanged" },
{ BLK_PERM_RESIZE, "resize" },
- { BLK_PERM_GRAPH_MOD, "change children" },
{ 0, NULL }
};
@@ -2599,8 +2600,7 @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
shared = 0;
}
- shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD |
- BLK_PERM_WRITE_UNCHANGED;
+ shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED;
if (bs->open_flags & BDRV_O_INACTIVE) {
shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
@@ -2718,7 +2718,6 @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
[BLOCK_PERMISSION_WRITE] = BLK_PERM_WRITE,
[BLOCK_PERMISSION_WRITE_UNCHANGED] = BLK_PERM_WRITE_UNCHANGED,
[BLOCK_PERMISSION_RESIZE] = BLK_PERM_RESIZE,
- [BLOCK_PERMISSION_GRAPH_MOD] = BLK_PERM_GRAPH_MOD,
};
QEMU_BUILD_BUG_ON(ARRAY_SIZE(permissions) != BLOCK_PERMISSION__MAX);
@@ -5544,8 +5543,6 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
update_inherits_from = bdrv_inherits_from_recursive(base, explicit_top);
/* success - we can delete the intermediate states, and link top->base */
- /* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once
- * we've figured out how they should work. */
if (!backing_file_str) {
bdrv_refresh_filename(base);
backing_file_str = base->filename;
@@ -7475,7 +7472,7 @@ static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
/* Note: This function may return false positives; it may return true
* even if opening the backing file specified by bs's image header
* would result in exactly bs->backing. */
-bool bdrv_backing_overridden(BlockDriverState *bs)
+static bool bdrv_backing_overridden(BlockDriverState *bs)
{
if (bs->backing) {
return strcmp(bs->auto_backing_file,
diff --git a/block/block-backend.c b/block/block-backend.c
index 12ef80ea17..23e727199b 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -822,16 +822,22 @@ BlockBackend *blk_by_public(BlockBackendPublic *public)
void blk_remove_bs(BlockBackend *blk)
{
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
- BlockDriverState *bs;
BdrvChild *root;
notifier_list_notify(&blk->remove_bs_notifiers, blk);
if (tgm->throttle_state) {
- bs = blk_bs(blk);
+ BlockDriverState *bs = blk_bs(blk);
+
+ /*
+ * Take a ref in case blk_bs() changes across bdrv_drained_begin(), for
+ * example, if a temporary filter node is removed by a blockjob.
+ */
+ bdrv_ref(bs);
bdrv_drained_begin(bs);
throttle_group_detach_aio_context(tgm);
throttle_group_attach_aio_context(tgm, qemu_get_aio_context());
bdrv_drained_end(bs);
+ bdrv_unref(bs);
}
blk_update_root_state(blk);
@@ -1705,6 +1711,7 @@ void blk_drain(BlockBackend *blk)
BlockDriverState *bs = blk_bs(blk);
if (bs) {
+ bdrv_ref(bs);
bdrv_drained_begin(bs);
}
@@ -1714,6 +1721,7 @@ void blk_drain(BlockBackend *blk)
if (bs) {
bdrv_drained_end(bs);
+ bdrv_unref(bs);
}
}
@@ -2044,10 +2052,13 @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
int ret;
if (bs) {
+ bdrv_ref(bs);
+
if (update_root_node) {
ret = bdrv_child_try_set_aio_context(bs, new_context, blk->root,
errp);
if (ret < 0) {
+ bdrv_unref(bs);
return ret;
}
}
@@ -2057,6 +2068,8 @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
throttle_group_attach_aio_context(tgm, new_context);
bdrv_drained_end(bs);
}
+
+ bdrv_unref(bs);
}
blk->ctx = new_context;
@@ -2326,11 +2339,13 @@ void blk_io_limits_disable(BlockBackend *blk)
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
assert(tgm->throttle_state);
if (bs) {
+ bdrv_ref(bs);
bdrv_drained_begin(bs);
}
throttle_group_unregister_tgm(tgm);
if (bs) {
bdrv_drained_end(bs);
+ bdrv_unref(bs);
}
}
diff --git a/block/commit.c b/block/commit.c
index 10cc5ff451..b1fc7b908b 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -370,7 +370,6 @@ void commit_start(const char *job_id, BlockDriverState *bs,
s->base = blk_new(s->common.job.aio_context,
base_perms,
BLK_PERM_CONSISTENT_READ
- | BLK_PERM_GRAPH_MOD
| BLK_PERM_WRITE_UNCHANGED);
ret = blk_insert_bs(s->base, base, errp);
if (ret < 0) {
diff --git a/block/curl.c b/block/curl.c
index 4a8ae2b269..6a6cd72975 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -125,7 +125,7 @@ static gboolean curl_drop_socket(void *key, void *value, void *opaque)
BDRVCURLState *s = socket->s;
aio_set_fd_handler(s->aio_context, socket->fd, false,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL);
return true;
}
@@ -173,19 +173,20 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
switch (action) {
case CURL_POLL_IN:
aio_set_fd_handler(s->aio_context, fd, false,
- curl_multi_do, NULL, NULL, socket);
+ curl_multi_do, NULL, NULL, NULL, socket);
break;
case CURL_POLL_OUT:
aio_set_fd_handler(s->aio_context, fd, false,
- NULL, curl_multi_do, NULL, socket);
+ NULL, curl_multi_do, NULL, NULL, socket);
break;
case CURL_POLL_INOUT:
aio_set_fd_handler(s->aio_context, fd, false,
- curl_multi_do, curl_multi_do, NULL, socket);
+ curl_multi_do, curl_multi_do,
+ NULL, NULL, socket);
break;
case CURL_POLL_REMOVE:
aio_set_fd_handler(s->aio_context, fd, false,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL);
break;
}
diff --git a/block/export/fuse.c b/block/export/fuse.c
index 823c126d23..6710d8aed8 100644
--- a/block/export/fuse.c
+++ b/block/export/fuse.c
@@ -223,7 +223,7 @@ static int setup_fuse_export(FuseExport *exp, const char *mountpoint,
aio_set_fd_handler(exp->common.ctx,
fuse_session_fd(exp->fuse_session), true,
- read_from_fuse_export, NULL, NULL, exp);
+ read_from_fuse_export, NULL, NULL, NULL, exp);
exp->fd_handler_set_up = true;
return 0;
@@ -267,7 +267,7 @@ static void fuse_export_shutdown(BlockExport *blk_exp)
if (exp->fd_handler_set_up) {
aio_set_fd_handler(exp->common.ctx,
fuse_session_fd(exp->fuse_session), true,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL);
exp->fd_handler_set_up = false;
}
}
diff --git a/block/file-posix.c b/block/file-posix.c
index b283093e5b..1f1756e192 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -106,10 +106,6 @@
#include <sys/diskslice.h>
#endif
-#ifdef CONFIG_XFS
-#include <xfs/xfs.h>
-#endif
-
/* OS X does not have O_DSYNC */
#ifndef O_DSYNC
#ifdef O_SYNC
@@ -156,9 +152,6 @@ typedef struct BDRVRawState {
int perm_change_flags;
BDRVReopenState *reopen_state;
-#ifdef CONFIG_XFS
- bool is_xfs:1;
-#endif
bool has_discard:1;
bool has_write_zeroes:1;
bool discard_zeroes:1;
@@ -409,14 +402,22 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
if (probe_logical_blocksize(fd, &bs->bl.request_alignment) < 0) {
bs->bl.request_alignment = 0;
}
-#ifdef CONFIG_XFS
- if (s->is_xfs) {
- struct dioattr da;
- if (xfsctl(NULL, fd, XFS_IOC_DIOINFO, &da) >= 0) {
- bs->bl.request_alignment = da.d_miniosz;
- /* The kernel returns wrong information for d_mem */
- /* s->buf_align = da.d_mem; */
- }
+
+#ifdef __linux__
+ /*
+ * The XFS ioctl definitions are shipped in extra packages that might
+ * not always be available. Since we just need the XFS_IOC_DIOINFO ioctl
+ * here, we simply use our own definition instead:
+ */
+ struct xfs_dioattr {
+ uint32_t d_mem;
+ uint32_t d_miniosz;
+ uint32_t d_maxiosz;
+ } da;
+ if (ioctl(fd, _IOR('X', 30, struct xfs_dioattr), &da) >= 0) {
+ bs->bl.request_alignment = da.d_miniosz;
+ /* The kernel returns wrong information for d_mem */
+ /* s->buf_align = da.d_mem; */
}
#endif
@@ -798,12 +799,6 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
#endif
s->needs_alignment = raw_needs_alignment(bs);
-#ifdef CONFIG_XFS
- if (platform_test_xfs_fd(s->fd)) {
- s->is_xfs = true;
- }
-#endif
-
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
if (S_ISREG(st.st_mode)) {
/* When extending regular files, we get zeros from the OS */
diff --git a/block/io_uring.c b/block/io_uring.c
index dfa475cc87..782afdb433 100644
--- a/block/io_uring.c
+++ b/block/io_uring.c
@@ -292,12 +292,14 @@ static bool qemu_luring_poll_cb(void *opaque)
{
LuringState *s = opaque;
- if (io_uring_cq_ready(&s->ring)) {
- luring_process_completions_and_submit(s);
- return true;
- }
+ return io_uring_cq_ready(&s->ring);
+}
+
+static void qemu_luring_poll_ready(void *opaque)
+{
+ LuringState *s = opaque;
- return false;
+ luring_process_completions_and_submit(s);
}
static void ioq_init(LuringQueue *io_q)
@@ -402,8 +404,8 @@ int coroutine_fn luring_co_submit(BlockDriverState *bs, LuringState *s, int fd,
void luring_detach_aio_context(LuringState *s, AioContext *old_context)
{
- aio_set_fd_handler(old_context, s->ring.ring_fd, false, NULL, NULL, NULL,
- s);
+ aio_set_fd_handler(old_context, s->ring.ring_fd, false,
+ NULL, NULL, NULL, NULL, s);
qemu_bh_delete(s->completion_bh);
s->aio_context = NULL;
}
@@ -413,7 +415,8 @@ void luring_attach_aio_context(LuringState *s, AioContext *new_context)
s->aio_context = new_context;
s->completion_bh = aio_bh_new(new_context, qemu_luring_completion_bh, s);
aio_set_fd_handler(s->aio_context, s->ring.ring_fd, false,
- qemu_luring_completion_cb, NULL, qemu_luring_poll_cb, s);
+ qemu_luring_completion_cb, NULL,
+ qemu_luring_poll_cb, qemu_luring_poll_ready, s);
}
LuringState *luring_init(Error **errp)
diff --git a/block/iscsi.c b/block/iscsi.c
index 57aa07a40d..51f2a5eeaa 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -363,7 +363,7 @@ iscsi_set_events(IscsiLun *iscsilun)
false,
(ev & POLLIN) ? iscsi_process_read : NULL,
(ev & POLLOUT) ? iscsi_process_write : NULL,
- NULL,
+ NULL, NULL,
iscsilun);
iscsilun->events = ev;
}
@@ -1534,7 +1534,7 @@ static void iscsi_detach_aio_context(BlockDriverState *bs)
IscsiLun *iscsilun = bs->opaque;
aio_set_fd_handler(iscsilun->aio_context, iscsi_get_fd(iscsilun->iscsi),
- false, NULL, NULL, NULL, NULL);
+ false, NULL, NULL, NULL, NULL, NULL);
iscsilun->events = 0;
if (iscsilun->nop_timer) {
diff --git a/block/linux-aio.c b/block/linux-aio.c
index f53ae72e21..4c423fcccf 100644
--- a/block/linux-aio.c
+++ b/block/linux-aio.c
@@ -263,12 +263,15 @@ static bool qemu_laio_poll_cb(void *opaque)
LinuxAioState *s = container_of(e, LinuxAioState, e);
struct io_event *events;
- if (!io_getevents_peek(s->ctx, &events)) {
- return false;
- }
+ return io_getevents_peek(s->ctx, &events);
+}
+
+static void qemu_laio_poll_ready(EventNotifier *opaque)
+{
+ EventNotifier *e = opaque;
+ LinuxAioState *s = container_of(e, LinuxAioState, e);
qemu_laio_process_completions_and_submit(s);
- return true;
}
static void ioq_init(LaioQueue *io_q)
@@ -427,7 +430,7 @@ int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context)
{
- aio_set_event_notifier(old_context, &s->e, false, NULL, NULL);
+ aio_set_event_notifier(old_context, &s->e, false, NULL, NULL, NULL);
qemu_bh_delete(s->completion_bh);
s->aio_context = NULL;
}
@@ -438,7 +441,8 @@ void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context)
s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s);
aio_set_event_notifier(new_context, &s->e, false,
qemu_laio_completion_cb,
- qemu_laio_poll_cb);
+ qemu_laio_poll_cb,
+ qemu_laio_poll_ready);
}
LinuxAioState *laio_init(Error **errp)
diff --git a/block/mirror.c b/block/mirror.c
index 959e3dfbd6..69b2c1c697 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -1139,10 +1139,7 @@ static void mirror_complete(Job *job, Error **errp)
replace_aio_context = bdrv_get_aio_context(s->to_replace);
aio_context_acquire(replace_aio_context);
- /* TODO Translate this into permission system. Current definition of
- * GRAPH_MOD would require to request it for the parents; they might
- * not even be BlockDriverStates, however, so a BdrvChild can't address
- * them. May need redefinition of GRAPH_MOD. */
+ /* TODO Translate this into child freeze system. */
error_setg(&s->replace_blocker,
"block device is in use by block-job-complete");
bdrv_op_block_all(s->to_replace, s->replace_blocker);
@@ -1666,7 +1663,7 @@ static BlockJob *mirror_start_job(
s = block_job_create(job_id, driver, NULL, mirror_top_bs,
BLK_PERM_CONSISTENT_READ,
BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
- BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD, speed,
+ BLK_PERM_WRITE, speed,
creation_flags, cb, opaque, errp);
if (!s) {
goto fail;
@@ -1710,9 +1707,7 @@ static BlockJob *mirror_start_job(
target_perms |= BLK_PERM_RESIZE;
}
- target_shared_perms |= BLK_PERM_CONSISTENT_READ
- | BLK_PERM_WRITE
- | BLK_PERM_GRAPH_MOD;
+ target_shared_perms |= BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE;
} else if (bdrv_chain_contains(bs, bdrv_skip_filters(target))) {
/*
* We may want to allow this in the future, but it would
@@ -1723,10 +1718,6 @@ static BlockJob *mirror_start_job(
goto fail;
}
- if (backing_mode != MIRROR_LEAVE_BACKING_CHAIN) {
- target_perms |= BLK_PERM_GRAPH_MOD;
- }
-
s->target = blk_new(s->common.job.aio_context,
target_perms, target_shared_perms);
ret = blk_insert_bs(s->target, target, errp);
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index 2ac4aedfff..bfb3c043a0 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -101,7 +101,7 @@ void hmp_drive_add(Monitor *mon, const QDict *qdict)
return;
}
- opts = drive_def(optstr);
+ opts = qemu_opts_parse_noisily(qemu_find_opts("drive"), optstr, false);
if (!opts)
return;
diff --git a/block/nfs.c b/block/nfs.c
index 577aea1d22..444c40b458 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -197,7 +197,7 @@ static void nfs_set_events(NFSClient *client)
false,
(ev & POLLIN) ? nfs_process_read : NULL,
(ev & POLLOUT) ? nfs_process_write : NULL,
- NULL, client);
+ NULL, NULL, client);
}
client->events = ev;
@@ -372,7 +372,7 @@ static void nfs_detach_aio_context(BlockDriverState *bs)
NFSClient *client = bs->opaque;
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
- false, NULL, NULL, NULL, NULL);
+ false, NULL, NULL, NULL, NULL, NULL);
client->events = 0;
}
@@ -390,7 +390,7 @@ static void nfs_client_close(NFSClient *client)
if (client->context) {
qemu_mutex_lock(&client->mutex);
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
- false, NULL, NULL, NULL, NULL);
+ false, NULL, NULL, NULL, NULL, NULL);
qemu_mutex_unlock(&client->mutex);
if (client->fh) {
nfs_close(client->context, client->fh);
diff --git a/block/nvme.c b/block/nvme.c
index fa360b9b3c..dd20de3865 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -605,10 +605,8 @@ out:
return ret;
}
-static bool nvme_poll_queue(NVMeQueuePair *q)
+static void nvme_poll_queue(NVMeQueuePair *q)
{
- bool progress = false;
-
const size_t cqe_offset = q->cq.head * NVME_CQ_ENTRY_BYTES;
NvmeCqe *cqe = (NvmeCqe *)&q->cq.queue[cqe_offset];
@@ -619,30 +617,23 @@ static bool nvme_poll_queue(NVMeQueuePair *q)
* cannot race with itself.
*/
if ((le16_to_cpu(cqe->status) & 0x1) == q->cq_phase) {
- return false;
+ return;
}
qemu_mutex_lock(&q->lock);
while (nvme_process_completion(q)) {
/* Keep polling */
- progress = true;
}
qemu_mutex_unlock(&q->lock);
-
- return progress;
}
-static bool nvme_poll_queues(BDRVNVMeState *s)
+static void nvme_poll_queues(BDRVNVMeState *s)
{
- bool progress = false;
int i;
for (i = 0; i < s->queue_count; i++) {
- if (nvme_poll_queue(s->queues[i])) {
- progress = true;
- }
+ nvme_poll_queue(s->queues[i]);
}
- return progress;
}
static void nvme_handle_event(EventNotifier *n)
@@ -703,8 +694,30 @@ static bool nvme_poll_cb(void *opaque)
EventNotifier *e = opaque;
BDRVNVMeState *s = container_of(e, BDRVNVMeState,
irq_notifier[MSIX_SHARED_IRQ_IDX]);
+ int i;
- return nvme_poll_queues(s);
+ for (i = 0; i < s->queue_count; i++) {
+ NVMeQueuePair *q = s->queues[i];
+ const size_t cqe_offset = q->cq.head * NVME_CQ_ENTRY_BYTES;
+ NvmeCqe *cqe = (NvmeCqe *)&q->cq.queue[cqe_offset];
+
+ /*
+ * q->lock isn't needed because nvme_process_completion() only runs in
+ * the event loop thread and cannot race with itself.
+ */
+ if ((le16_to_cpu(cqe->status) & 0x1) != q->cq_phase) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void nvme_poll_ready(EventNotifier *e)
+{
+ BDRVNVMeState *s = container_of(e, BDRVNVMeState,
+ irq_notifier[MSIX_SHARED_IRQ_IDX]);
+
+ nvme_poll_queues(s);
}
static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
@@ -839,7 +852,8 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
}
aio_set_event_notifier(bdrv_get_aio_context(bs),
&s->irq_notifier[MSIX_SHARED_IRQ_IDX],
- false, nvme_handle_event, nvme_poll_cb);
+ false, nvme_handle_event, nvme_poll_cb,
+ nvme_poll_ready);
if (!nvme_identify(bs, namespace, errp)) {
ret = -EIO;
@@ -924,7 +938,7 @@ static void nvme_close(BlockDriverState *bs)
g_free(s->queues);
aio_set_event_notifier(bdrv_get_aio_context(bs),
&s->irq_notifier[MSIX_SHARED_IRQ_IDX],
- false, NULL, NULL);
+ false, NULL, NULL, NULL);
event_notifier_cleanup(&s->irq_notifier[MSIX_SHARED_IRQ_IDX]);
qemu_vfio_pci_unmap_bar(s->vfio, 0, s->bar0_wo_map,
0, sizeof(NvmeBar) + NVME_DOORBELL_SIZE);
@@ -1520,7 +1534,7 @@ static void nvme_detach_aio_context(BlockDriverState *bs)
aio_set_event_notifier(bdrv_get_aio_context(bs),
&s->irq_notifier[MSIX_SHARED_IRQ_IDX],
- false, NULL, NULL);
+ false, NULL, NULL, NULL);
}
static void nvme_attach_aio_context(BlockDriverState *bs,
@@ -1530,7 +1544,8 @@ static void nvme_attach_aio_context(BlockDriverState *bs,
s->aio_context = new_context;
aio_set_event_notifier(new_context, &s->irq_notifier[MSIX_SHARED_IRQ_IDX],
- false, nvme_handle_event, nvme_poll_cb);
+ false, nvme_handle_event, nvme_poll_cb,
+ nvme_poll_ready);
for (unsigned i = 0; i < s->queue_count; i++) {
NVMeQueuePair *q = s->queues[i];
diff --git a/block/ssh.c b/block/ssh.c
index e0fbb4934b..3b5bf34031 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -990,7 +990,7 @@ static void restart_coroutine(void *opaque)
AioContext *ctx = bdrv_get_aio_context(bs);
trace_ssh_restart_coroutine(restart->co);
- aio_set_fd_handler(ctx, s->sock, false, NULL, NULL, NULL, NULL);
+ aio_set_fd_handler(ctx, s->sock, false, NULL, NULL, NULL, NULL, NULL);
aio_co_wake(restart->co);
}
@@ -1020,7 +1020,7 @@ static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs)
trace_ssh_co_yield(s->sock, rd_handler, wr_handler);
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
- false, rd_handler, wr_handler, NULL, &restart);
+ false, rd_handler, wr_handler, NULL, NULL, &restart);
qemu_coroutine_yield();
trace_ssh_co_yield_back(s->sock);
}
diff --git a/block/vvfat.c b/block/vvfat.c
index 5dacc6cfac..b2b58d93b8 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -882,7 +882,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
return 0;
}
-static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
+static inline int32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
{
return (sector_num - s->offset_to_root_dir) / s->sectors_per_cluster;
}
@@ -1230,6 +1230,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
dirname, cyls, heads, secs));
s->sector_count = cyls * heads * secs - s->offset_to_bootsector;
+ bs->total_sectors = cyls * heads * secs;
if (qemu_opt_get_bool(opts, "rw", false)) {
if (!bdrv_is_read_only(bs)) {
@@ -1250,8 +1251,6 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
}
}
- bs->total_sectors = cyls * heads * secs;
-
if (init_directories(s, dirname, heads, secs, errp)) {
ret = -EIO;
goto fail;
@@ -2982,6 +2981,7 @@ static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
{
BDRVVVFATState *s = bs->opaque;
int i, ret;
+ int first_cluster, last_cluster;
DLOG(checkpoint());
@@ -3000,9 +3000,20 @@ DLOG(checkpoint());
if (sector_num < s->offset_to_fat)
return -1;
- for (i = sector2cluster(s, sector_num);
- i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
- mapping_t* mapping = find_mapping_for_cluster(s, i);
+ /*
+ * Values will be negative for writes to the FAT, which is located before
+ * the root directory.
+ */
+ first_cluster = sector2cluster(s, sector_num);
+ last_cluster = sector2cluster(s, sector_num + nb_sectors - 1);
+
+ for (i = first_cluster; i <= last_cluster;) {
+ mapping_t *mapping = NULL;
+
+ if (i >= 0) {
+ mapping = find_mapping_for_cluster(s, i);
+ }
+
if (mapping) {
if (mapping->read_only) {
fprintf(stderr, "Tried to write to write-protected file %s\n",
@@ -3042,8 +3053,9 @@ DLOG(checkpoint());
}
}
i = mapping->end;
- } else
+ } else {
i++;
+ }
}
/*
@@ -3057,10 +3069,11 @@ DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sec
return ret;
}
- for (i = sector2cluster(s, sector_num);
- i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
- if (i >= 0)
+ for (i = first_cluster; i <= last_cluster; i++) {
+ if (i >= 0) {
s->used_clusters[i] |= USED_ALLOCATED;
+ }
+ }
DLOG(checkpoint());
/* TODO: add timeout */
@@ -3147,8 +3160,8 @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
}
opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort);
- qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512,
- &error_abort);
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE,
+ bs->total_sectors * BDRV_SECTOR_SIZE, &error_abort);
qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:", &error_abort);
ret = bdrv_create(bdrv_qcow, s->qcow_filename, opts, errp);
diff --git a/block/win32-aio.c b/block/win32-aio.c
index b7221a272f..c57e10c997 100644
--- a/block/win32-aio.c
+++ b/block/win32-aio.c
@@ -172,7 +172,7 @@ int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile)
void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
AioContext *old_context)
{
- aio_set_event_notifier(old_context, &aio->e, false, NULL, NULL);
+ aio_set_event_notifier(old_context, &aio->e, false, NULL, NULL, NULL);
aio->aio_ctx = NULL;
}
@@ -181,7 +181,7 @@ void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
{
aio->aio_ctx = new_context;
aio_set_event_notifier(new_context, &aio->e, false,
- win32_aio_completion_cb, NULL);
+ win32_aio_completion_cb, NULL, NULL);
}
QEMUWin32AIOState *win32_aio_init(void)
diff --git a/blockdev.c b/blockdev.c
index b5ff9b854e..8197165bb5 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -168,23 +168,6 @@ void blockdev_auto_del(BlockBackend *blk)
}
}
-/**
- * Returns the current mapping of how many units per bus
- * a particular interface can support.
- *
- * A positive integer indicates n units per bus.
- * 0 implies the mapping has not been established.
- * -1 indicates an invalid BlockInterfaceType was given.
- */
-int drive_get_max_devs(BlockInterfaceType type)
-{
- if (type >= IF_IDE && type < IF_COUNT) {
- return if_max_devs[type];
- }
-
- return -1;
-}
-
static int drive_index_to_bus_id(BlockInterfaceType type, int index)
{
int max_devs = if_max_devs[type];
@@ -197,17 +180,12 @@ static int drive_index_to_unit_id(BlockInterfaceType type, int index)
return max_devs ? index % max_devs : index;
}
-QemuOpts *drive_def(const char *optstr)
-{
- return qemu_opts_parse_noisily(qemu_find_opts("drive"), optstr, false);
-}
-
QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
const char *optstr)
{
QemuOpts *opts;
- opts = drive_def(optstr);
+ opts = qemu_opts_parse_noisily(qemu_find_opts("drive"), optstr, false);
if (!opts) {
return NULL;
}
diff --git a/bsd-user/special-errno.h b/bsd-user/include/special-errno.h
index 03599d9b5a..03599d9b5a 100644
--- a/bsd-user/special-errno.h
+++ b/bsd-user/include/special-errno.h
diff --git a/bsd-user/meson.build b/bsd-user/meson.build
index 9fcb80c3fa..8380fa44c2 100644
--- a/bsd-user/meson.build
+++ b/bsd-user/meson.build
@@ -4,7 +4,7 @@ endif
bsd_user_ss = ss.source_set()
-common_user_inc += include_directories('.')
+common_user_inc += include_directories('include')
bsd_user_ss.add(files(
'bsdload.c',
diff --git a/common-user/meson.build b/common-user/meson.build
index 5cb42bc664..26212dda5c 100644
--- a/common-user/meson.build
+++ b/common-user/meson.build
@@ -1,6 +1,6 @@
common_user_inc += include_directories('host/' / host_arch)
-common_user_ss.add(files(
+user_ss.add(files(
'safe-syscall.S',
'safe-syscall-error.c',
))
diff --git a/configs/devices/mips-softmmu/common.mak b/configs/devices/mips-softmmu/common.mak
index 752b62b1e6..d2202c839e 100644
--- a/configs/devices/mips-softmmu/common.mak
+++ b/configs/devices/mips-softmmu/common.mak
@@ -7,7 +7,7 @@ CONFIG_ISA_BUS=y
CONFIG_PCI=y
CONFIG_PCI_DEVICES=y
CONFIG_VGA_ISA=y
-CONFIG_VGA_ISA_MM=y
+CONFIG_VGA_MMIO=y
CONFIG_VGA_CIRRUS=y
CONFIG_VMWARE_VGA=y
CONFIG_SERIAL=y
diff --git a/configure b/configure
index 030728d11e..e1a31fb332 100755
--- a/configure
+++ b/configure
@@ -78,7 +78,6 @@ TMPC="${TMPDIR1}/${TMPB}.c"
TMPO="${TMPDIR1}/${TMPB}.o"
TMPCXX="${TMPDIR1}/${TMPB}.cxx"
TMPE="${TMPDIR1}/${TMPB}.exe"
-TMPTXT="${TMPDIR1}/${TMPB}.txt"
rm -f config.log
@@ -291,7 +290,6 @@ EXTRA_CXXFLAGS=""
EXTRA_LDFLAGS=""
xen_ctrl_version="$default_feature"
-xfs="$default_feature"
membarrier="$default_feature"
vhost_kernel="$default_feature"
vhost_net="$default_feature"
@@ -309,21 +307,16 @@ debug="no"
sanitizers="no"
tsan="no"
fortify_source="$default_feature"
-strip_opt="yes"
-mingw32="no"
gcov="no"
EXESUF=""
modules="no"
module_upgrades="no"
prefix="/usr/local"
qemu_suffix="qemu"
-bsd="no"
-linux="no"
-solaris="no"
profiler="no"
softmmu="yes"
-linux_user="no"
-bsd_user="no"
+linux_user=""
+bsd_user=""
pkgversion=""
pie=""
qom_cast_debug="yes"
@@ -333,8 +326,6 @@ opengl="$default_feature"
cpuid_h="no"
avx2_opt="$default_feature"
guest_agent="$default_feature"
-guest_agent_with_vss="no"
-guest_agent_ntddscsi="no"
vss_win32_sdk="$default_feature"
win_sdk="no"
want_tools="$default_feature"
@@ -529,6 +520,10 @@ fi
# OS specific
+mingw32="no"
+bsd="no"
+linux="no"
+solaris="no"
case $targetos in
windows)
mingw32="yes"
@@ -540,7 +535,6 @@ gnu/kfreebsd)
;;
freebsd)
bsd="yes"
- bsd_user="yes"
make="${MAKE-gmake}"
# needed for kinfo_getvmmap(3) in libutil.h
;;
@@ -585,7 +579,6 @@ haiku)
;;
linux)
linux="yes"
- linux_user="yes"
vhost_user=${default_feature:-yes}
;;
esac
@@ -896,7 +889,6 @@ for opt do
debug_tcg="yes"
debug_mutex="yes"
debug="yes"
- strip_opt="no"
fortify_source="no"
;;
--enable-sanitizers) sanitizers="yes"
@@ -907,8 +899,6 @@ for opt do
;;
--disable-tsan) tsan="no"
;;
- --disable-strip) strip_opt="no"
- ;;
--disable-slirp) slirp="disabled"
;;
--enable-slirp) slirp="enabled"
@@ -1021,10 +1011,6 @@ for opt do
;;
--enable-opengl) opengl="yes"
;;
- --disable-xfsctl) xfs="no"
- ;;
- --enable-xfsctl) xfs="yes"
- ;;
--disable-zlib-test)
;;
--enable-guest-agent) guest_agent="yes"
@@ -1265,18 +1251,26 @@ if eval test -z "\${cross_cc_$cpu}"; then
cross_cc_vars="$cross_cc_vars cross_cc_${cpu}"
fi
-# For user-mode emulation the host arch has to be one we explicitly
-# support, even if we're using TCI.
-if [ "$ARCH" = "unknown" ]; then
- bsd_user="no"
- linux_user="no"
-fi
-
default_target_list=""
deprecated_targets_list=ppc64abi32-linux-user
deprecated_features=""
mak_wilds=""
+if [ "$linux_user" != no ]; then
+ if [ "$targetos" = linux ] && [ -d $source_path/linux-user/include/host/$cpu ]; then
+ linux_user=yes
+ elif [ "$linux_user" = yes ]; then
+ error_exit "linux-user not supported on this architecture"
+ fi
+fi
+if [ "$bsd_user" != no ]; then
+ if [ "$bsd_user" = "" ]; then
+ test $targetos = freebsd && bsd_user=yes
+ fi
+ if [ "$bsd_user" = yes ] && ! [ -d $source_path/bsd-user/$targetos ]; then
+ error_exit "bsd-user not supported on this host OS"
+ fi
+fi
if [ "$softmmu" = "yes" ]; then
mak_wilds="${mak_wilds} $source_path/configs/targets/*-softmmu.mak"
fi
@@ -1367,7 +1361,6 @@ Advanced options (experts only):
--enable-debug enable common debug build options
--enable-sanitizers enable default sanitizers
--enable-tsan enable thread sanitizer
- --disable-strip disable stripping binaries
--disable-werror disable compilation abort on warning
--disable-stack-protector disable compiler-provided stack protection
--audio-drv-list=LIST set audio drivers to try if -audiodev is not used
@@ -1431,7 +1424,6 @@ cat << EOF
avx512f AVX512F optimization support
replication replication support
opengl opengl support
- xfsctl xfsctl support
qom-cast-debug cast debugging support
tools build qemu-io, qemu-nbd and qemu-img tools
bochs bochs image format support
@@ -1702,6 +1694,7 @@ if test "$static" = "yes" ; then
plugins="no"
fi
fi
+test "$plugins" = "" && plugins=yes
cat > $TMPC << EOF
@@ -2324,91 +2317,6 @@ EOF
fi
##########################################
-# xfsctl() probe, used for file-posix.c
-if test "$xfs" != "no" ; then
- cat > $TMPC << EOF
-#include <stddef.h> /* NULL */
-#include <xfs/xfs.h>
-int main(void)
-{
- xfsctl(NULL, 0, 0, NULL);
- return 0;
-}
-EOF
- if compile_prog "" "" ; then
- xfs="yes"
- else
- if test "$xfs" = "yes" ; then
- feature_not_found "xfs" "Install xfsprogs/xfslibs devel"
- fi
- xfs=no
- fi
-fi
-
-##########################################
-# plugin linker support probe
-
-if test "$plugins" != "no"; then
-
- #########################################
- # See if --dynamic-list is supported by the linker
-
- ld_dynamic_list="no"
- cat > $TMPTXT <<EOF
-{
- foo;
-};
-EOF
-
- cat > $TMPC <<EOF
-#include <stdio.h>
-void foo(void);
-
-void foo(void)
-{
- printf("foo\n");
-}
-
-int main(void)
-{
- foo();
- return 0;
-}
-EOF
-
- if compile_prog "" "-Wl,--dynamic-list=$TMPTXT" ; then
- ld_dynamic_list="yes"
- fi
-
- #########################################
- # See if -exported_symbols_list is supported by the linker
-
- ld_exported_symbols_list="no"
- cat > $TMPTXT <<EOF
- _foo
-EOF
-
- if compile_prog "" "-Wl,-exported_symbols_list,$TMPTXT" ; then
- ld_exported_symbols_list="yes"
- fi
-
- if test "$ld_dynamic_list" = "no" &&
- test "$ld_exported_symbols_list" = "no" ; then
- if test "$plugins" = "yes"; then
- error_exit \
- "Plugin support requires dynamic linking and specifying a set of symbols " \
- "that are exported to plugins. Unfortunately your linker doesn't " \
- "support the flag (--dynamic-list or -exported_symbols_list) used " \
- "for this purpose."
- else
- plugins="no"
- fi
- else
- plugins="yes"
- fi
-fi
-
-##########################################
# glib support probe
glib_req_ver=2.56
@@ -2639,6 +2547,7 @@ fi
##########################################
# check if we have VSS SDK headers for win
+guest_agent_with_vss="no"
if test "$mingw32" = "yes" && test "$guest_agent" != "no" && \
test "$vss_win32_sdk" != "no" ; then
case "$vss_win32_sdk" in
@@ -2669,7 +2578,6 @@ EOF
echo "ERROR: The headers are extracted in the directory \`inc'."
feature_not_found "VSS support"
fi
- guest_agent_with_vss="no"
fi
fi
@@ -2696,6 +2604,7 @@ fi
##########################################
# check if mingw environment provides a recent ntddscsi.h
+guest_agent_ntddscsi="no"
if test "$mingw32" = "yes" && test "$guest_agent" != "no"; then
cat > $TMPC << EOF
#include <windows.h>
@@ -3400,9 +3309,6 @@ echo "GIT_SUBMODULES_ACTION=$git_submodules_action" >> $config_host_mak
if test "$debug_tcg" = "yes" ; then
echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
fi
-if test "$strip_opt" = "yes" ; then
- echo "STRIP=${strip}" >> $config_host_mak
-fi
if test "$mingw32" = "yes" ; then
echo "CONFIG_WIN32=y" >> $config_host_mak
if test "$guest_agent_with_vss" = "yes" ; then
@@ -3456,9 +3362,6 @@ echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_whitelist" >> $config_host_mak
if test "$block_drv_whitelist_tools" = "yes" ; then
echo "CONFIG_BDRV_WHITELIST_TOOLS=y" >> $config_host_mak
fi
-if test "$xfs" = "yes" ; then
- echo "CONFIG_XFS=y" >> $config_host_mak
-fi
qemu_version=$(head $source_path/VERSION)
echo "PKGVERSION=$pkgversion" >>$config_host_mak
echo "SRC_PATH=$source_path" >> $config_host_mak
@@ -3645,22 +3548,6 @@ fi
if test "$plugins" = "yes" ; then
echo "CONFIG_PLUGIN=y" >> $config_host_mak
- # Copy the export object list to the build dir
- if test "$ld_dynamic_list" = "yes" ; then
- echo "CONFIG_HAS_LD_DYNAMIC_LIST=yes" >> $config_host_mak
- ld_symbols=qemu-plugins-ld.symbols
- cp "$source_path/plugins/qemu-plugins.symbols" $ld_symbols
- elif test "$ld_exported_symbols_list" = "yes" ; then
- echo "CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST=yes" >> $config_host_mak
- ld64_symbols=qemu-plugins-ld64.symbols
- echo "# Automatically generated by configure - do not modify" > $ld64_symbols
- grep 'qemu_' "$source_path/plugins/qemu-plugins.symbols" | sed 's/;//g' | \
- sed -E 's/^[[:space:]]*(.*)/_\1/' >> $ld64_symbols
- else
- error_exit \
- "If \$plugins=yes, either \$ld_dynamic_list or " \
- "\$ld_exported_symbols_list should have been set to 'yes'."
- fi
fi
if test -n "$gdb_bin"; then
@@ -3699,6 +3586,7 @@ echo "GLIB_LIBS=$glib_libs" >> $config_host_mak
echo "GLIB_VERSION=$(pkg-config --modversion glib-2.0)" >> $config_host_mak
echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak
echo "LD_I386_EMULATION=$ld_i386_emulation" >> $config_host_mak
+echo "STRIP=$strip" >> $config_host_mak
echo "EXESUF=$EXESUF" >> $config_host_mak
echo "LIBS_QGA=$libs_qga" >> $config_host_mak
@@ -3776,9 +3664,6 @@ fi
# so the build tree will be missing the link back to the new file, and
# tests might fail. Prefer to keep the relevant files in their own
# directory and symlink the directory instead.
-# UNLINK is used to remove symlinks from older development versions
-# that might get into the way when doing "git update" without doing
-# a "make distclean" in between.
LINKS="Makefile"
LINKS="$LINKS tests/tcg/Makefile.target"
LINKS="$LINKS pc-bios/optionrom/Makefile"
@@ -3790,7 +3675,6 @@ LINKS="$LINKS tests/avocado tests/data"
LINKS="$LINKS tests/qemu-iotests/check"
LINKS="$LINKS python"
LINKS="$LINKS contrib/plugins/Makefile "
-UNLINK="pc-bios/keymaps"
for bios_file in \
$source_path/pc-bios/*.bin \
$source_path/pc-bios/*.elf \
@@ -3812,11 +3696,6 @@ for f in $LINKS ; do
symlink "$source_path/$f" "$f"
fi
done
-for f in $UNLINK ; do
- if [ -L "$f" ]; then
- rm -f "$f"
- fi
-done
(for i in $cross_cc_vars; do
export $i
@@ -3825,7 +3704,8 @@ export target_list source_path use_containers cpu
$source_path/tests/tcg/configure.sh)
# temporary config to build submodules
-for rom in seabios; do
+if test -f $source_path/roms/seabios/Makefile; then
+ for rom in seabios; do
config_mak=roms/$rom/config.mak
echo "# Automatically generated by configure - do not modify" > $config_mak
echo "SRC_PATH=$source_path/roms/$rom" >> $config_mak
@@ -3838,7 +3718,8 @@ for rom in seabios; do
echo "IASL=$iasl" >> $config_mak
echo "LD=$ld" >> $config_mak
echo "RANLIB=$ranlib" >> $config_mak
-done
+ done
+fi
config_mak=pc-bios/optionrom/config.mak
echo "# Automatically generated by configure - do not modify" > $config_mak
@@ -3925,7 +3806,6 @@ if test "$skip_meson" = no; then
-Doptimization=$(if test "$debug" = yes; then echo 0; else echo 2; fi) \
-Ddebug=$(if test "$debug_info" = yes; then echo true; else echo false; fi) \
-Dwerror=$(if test "$werror" = yes; then echo true; else echo false; fi) \
- -Dstrip=$(if test "$strip_opt" = yes; then echo true; else echo false; fi) \
-Db_pie=$(if test "$pie" = yes; then echo true; else echo false; fi) \
-Db_coverage=$(if test "$gcov" = yes; then echo true; else echo false; fi) \
-Db_lto=$lto -Dcfi=$cfi -Dtcg=$tcg -Dxen=$xen \
@@ -3956,17 +3836,6 @@ if test -n "${deprecated_features}"; then
echo " features: ${deprecated_features}"
fi
-# Create list of config switches that should be poisoned in common code...
-# but filter out CONFIG_TCG and CONFIG_USER_ONLY which are special.
-target_configs_h=$(ls *-config-devices.h *-config-target.h 2>/dev/null)
-if test -n "$target_configs_h" ; then
- sed -n -e '/CONFIG_TCG/d' -e '/CONFIG_USER_ONLY/d' \
- -e '/^#define / { s///; s/ .*//; s/^/#pragma GCC poison /p; }' \
- $target_configs_h | sort -u > config-poison.h
-else
- :> config-poison.h
-fi
-
# Save the configure command line for later reuse.
cat <<EOD >config.status
#!/bin/sh
diff --git a/contrib/elf2dmp/meson.build b/contrib/elf2dmp/meson.build
index 4d86cb390a..6707d43c4f 100644
--- a/contrib/elf2dmp/meson.build
+++ b/contrib/elf2dmp/meson.build
@@ -1,5 +1,5 @@
if curl.found()
- executable('elf2dmp', files('main.c', 'addrspace.c', 'download.c', 'pdb.c', 'qemu_elf.c'),
+ executable('elf2dmp', files('main.c', 'addrspace.c', 'download.c', 'pdb.c', 'qemu_elf.c'), genh,
dependencies: [glib, curl],
install: true)
endif
diff --git a/contrib/ivshmem-client/meson.build b/contrib/ivshmem-client/meson.build
index 1b171efb4f..ce8dcca84d 100644
--- a/contrib/ivshmem-client/meson.build
+++ b/contrib/ivshmem-client/meson.build
@@ -1,4 +1,4 @@
-executable('ivshmem-client', files('ivshmem-client.c', 'main.c'),
+executable('ivshmem-client', files('ivshmem-client.c', 'main.c'), genh,
dependencies: glib,
build_by_default: targetos == 'linux',
install: false)
diff --git a/contrib/ivshmem-server/meson.build b/contrib/ivshmem-server/meson.build
index 3a53942201..c6c3c82e89 100644
--- a/contrib/ivshmem-server/meson.build
+++ b/contrib/ivshmem-server/meson.build
@@ -1,4 +1,4 @@
-executable('ivshmem-server', files('ivshmem-server.c', 'main.c'),
+executable('ivshmem-server', files('ivshmem-server.c', 'main.c'), genh,
dependencies: [qemuutil, rt],
build_by_default: targetos == 'linux',
install: false)
diff --git a/contrib/rdmacm-mux/meson.build b/contrib/rdmacm-mux/meson.build
index 6cc5016747..7674f54cc5 100644
--- a/contrib/rdmacm-mux/meson.build
+++ b/contrib/rdmacm-mux/meson.build
@@ -2,7 +2,7 @@ if 'CONFIG_PVRDMA' in config_host
# if not found, CONFIG_PVRDMA should not be set
# FIXME: broken on big endian architectures
libumad = cc.find_library('ibumad', required: true)
- executable('rdmacm-mux', files('main.c'),
+ executable('rdmacm-mux', files('main.c'), genh,
dependencies: [glib, libumad],
build_by_default: false,
install: false)
diff --git a/docs/papr-pef.txt b/docs/papr-pef.txt
deleted file mode 100644
index 72550e9bf8..0000000000
--- a/docs/papr-pef.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-POWER (PAPR) Protected Execution Facility (PEF)
-===============================================
-
-Protected Execution Facility (PEF), also known as Secure Guest support
-is a feature found on IBM POWER9 and POWER10 processors.
-
-If a suitable firmware including an Ultravisor is installed, it adds
-an extra memory protection mode to the CPU. The ultravisor manages a
-pool of secure memory which cannot be accessed by the hypervisor.
-
-When this feature is enabled in QEMU, a guest can use ultracalls to
-enter "secure mode". This transfers most of its memory to secure
-memory, where it cannot be eavesdropped by a compromised hypervisor.
-
-Launching
----------
-
-To launch a guest which will be permitted to enter PEF secure mode:
-
-# ${QEMU} \
- -object pef-guest,id=pef0 \
- -machine confidential-guest-support=pef0 \
- ...
-
-Live Migration
-----------------
-
-Live migration is not yet implemented for PEF guests. For
-consistency, we currently prevent migration if the PEF feature is
-enabled, whether or not the guest has actually entered secure mode.
diff --git a/docs/specs/ppc-spapr-hcalls.rst b/docs/specs/ppc-spapr-hcalls.rst
index 28daf9734a..6cdcef2026 100644
--- a/docs/specs/ppc-spapr-hcalls.rst
+++ b/docs/specs/ppc-spapr-hcalls.rst
@@ -1,13 +1,12 @@
+======================
sPAPR hypervisor calls
-----------------------
+======================
When used with the ``pseries`` machine type, ``qemu-system-ppc64`` implements
-a set of hypervisor calls (a.k.a. hcalls) defined in the `Linux on Power
-Architecture Reference document (LoPAR)
-<https://cdn.openpowerfoundation.org/wp-content/uploads/2020/07/LoPAR-20200812.pdf>`_.
-This document is a subset of the Power Architecture Platform Reference (PAPR+)
-specification (IBM internal only), which is what PowerVM, the IBM proprietary
-hypervisor, adheres to.
+a set of hypervisor calls (a.k.a. hcalls) defined in the Linux on Power
+Architecture Reference ([LoPAR]_) document. This document is a subset of the
+Power Architecture Platform Reference (PAPR+) specification (IBM internal only),
+which is what PowerVM, the IBM proprietary hypervisor, adheres to.
The subset in LoPAR is selected based on the requirements of Linux as a guest.
@@ -18,8 +17,8 @@ running in the guest and QEMU.
All those hypercalls start at hcall number 0xf000 which correspond
to an implementation specific range in PAPR.
-H_RTAS (0xf000)
-^^^^^^^^^^^^^^^
+``H_RTAS (0xf000)``
+===================
RTAS stands for Run-Time Abstraction Sercies and is a set of runtime services
generally provided by the firmware inside the guest to the operating system. It
@@ -44,8 +43,8 @@ Returns:
``H_PARAMETER``: Unknown token.
-H_LOGICAL_MEMOP (0xf001)
-^^^^^^^^^^^^^^^^^^^^^^^^
+``H_LOGICAL_MEMOP (0xf001)``
+============================
When the guest runs in "real mode" (in powerpc terminology this means with MMU
disabled, i.e. guest effective address equals to guest physical address), it
diff --git a/docs/system/ppc/pseries.rst b/docs/system/ppc/pseries.rst
index 72e315eff6..1689324815 100644
--- a/docs/system/ppc/pseries.rst
+++ b/docs/system/ppc/pseries.rst
@@ -1,19 +1,18 @@
+===================================
pSeries family boards (``pseries``)
===================================
-The Power machine para-virtualized environment described by the `Linux on Power
-Architecture Reference document (LoPAR)
-<https://openpowerfoundation.org/wp-content/uploads/2020/07/LoPAR-20200812.pdf>`_
-is called pSeries. This environment is also known as sPAPR, System p guests, or
-simply Power Linux guests (although it is capable of running other operating
-systems, such as AIX).
+The Power machine para-virtualized environment described by the Linux on Power
+Architecture Reference ([LoPAR]_) document is called pSeries. This environment
+is also known as sPAPR, System p guests, or simply Power Linux guests (although
+it is capable of running other operating systems, such as AIX).
Even though pSeries is designed to behave as a guest environment, it is also
capable of acting as a hypervisor OS, providing, on that role, nested
virtualization capabilities.
Supported devices
------------------
+=================
* Multi processor support for many Power processors generations: POWER7,
POWER7+, POWER8, POWER8NVL, POWER9, and Power10. Support for POWER5+ exists,
@@ -26,12 +25,12 @@ Supported devices
* PCIe device pass through.
Missing devices
----------------
+===============
* SPICE support.
Firmware
---------
+========
`SLOF <https://github.com/aik/SLOF>`_ (Slimline Open Firmware) is an
implementation of the `IEEE 1275-1994, Standard for Boot (Initialization
@@ -42,14 +41,14 @@ QEMU includes a prebuilt image of SLOF which is updated when a more recent
version is required.
Build directions
-----------------
+================
.. code-block:: bash
./configure --target-list=ppc64-softmmu && make
Running instructions
---------------------
+====================
Someone can select the pSeries machine type by running QEMU with the following
options:
@@ -59,7 +58,7 @@ options:
qemu-system-ppc64 -M pseries <other QEMU arguments>
sPAPR devices
--------------
+=============
The sPAPR specification defines a set of para-virtualized devices, which are
also supported by the pSeries machine in QEMU and can be instantiated with the
@@ -102,11 +101,9 @@ device, or specify one with an ID
NVRAM device with ``-global spapr-nvram.drive=pfid``.
sPAPR specification
-^^^^^^^^^^^^^^^^^^^
+-------------------
-The main source of documentation on the sPAPR standard is the `Linux on Power
-Architecture Reference document (LoPAR)
-<https://openpowerfoundation.org/wp-content/uploads/2020/07/LoPAR-20200812.pdf>`_.
+The main source of documentation on the sPAPR standard is the [LoPAR]_ document.
However, documentation specific to QEMU's implementation of the specification
can also be found in QEMU documentation:
@@ -124,7 +121,7 @@ Other documentation available in QEMU docs directory:
(``/docs/specs/ppc-spapr-uv-hcalls.txt``).
Switching between the KVM-PR and KVM-HV kernel module
------------------------------------------------------
+=====================================================
Currently, there are two implementations of KVM on Power, ``kvm_hv.ko`` and
``kvm_pr.ko``.
@@ -139,7 +136,7 @@ possible to switch between the two modes with the ``kvm-type`` parameter:
instead.
KVM-PR
-^^^^^^
+------
KVM-PR uses the so-called **PR**\ oblem state of the PPC CPUs to run the guests,
i.e. the virtual machine is run in user mode and all privileged instructions
@@ -166,7 +163,7 @@ In order to run KVM-PR guests with POWER9 processors, someone will need to start
QEMU with ``kernel_irqchip=off`` command line option.
KVM-HV
-^^^^^^
+------
KVM-HV uses the hypervisor mode of more recent Power processors, that allow
access to the bare metal hardware directly. Although POWER7 had this capability,
@@ -188,7 +185,7 @@ CPUs generations, e.g. you can run a POWER7 guest on a POWER8 host by using
``-cpu POWER8,compat=power7`` as parameter to QEMU.
Modules support
----------------
+===============
As noticed in the sections above, each module can run in a different
environment. The following table shows with which environment each module can
@@ -230,9 +227,45 @@ nested. Combinations not shown in the table are not available.
.. [3] Introduced on Power10 machines.
+
+POWER (PAPR) Protected Execution Facility (PEF)
+-----------------------------------------------
+
+Protected Execution Facility (PEF), also known as Secure Guest support
+is a feature found on IBM POWER9 and POWER10 processors.
+
+If a suitable firmware including an Ultravisor is installed, it adds
+an extra memory protection mode to the CPU. The ultravisor manages a
+pool of secure memory which cannot be accessed by the hypervisor.
+
+When this feature is enabled in QEMU, a guest can use ultracalls to
+enter "secure mode". This transfers most of its memory to secure
+memory, where it cannot be eavesdropped by a compromised hypervisor.
+
+Launching
+^^^^^^^^^
+
+To launch a guest which will be permitted to enter PEF secure mode::
+
+ $ qemu-system-ppc64 \
+ -object pef-guest,id=pef0 \
+ -machine confidential-guest-support=pef0 \
+ ...
+
+Live Migration
+^^^^^^^^^^^^^^
+
+Live migration is not yet implemented for PEF guests. For
+consistency, QEMU currently prevents migration if the PEF feature is
+enabled, whether or not the guest has actually entered secure mode.
+
+
Maintainer contact information
-------------------------------
+==============================
Cédric Le Goater <clg@kaod.org>
Daniel Henrique Barboza <danielhb413@gmail.com>
+
+.. [LoPAR] `Linux on Power Architecture Reference document (LoPAR) revision
+ 2.9 <https://openpowerfoundation.org/wp-content/uploads/2020/07/LoPAR-20200812.pdf>`_.
diff --git a/docs/tools/qemu-storage-daemon.rst b/docs/tools/qemu-storage-daemon.rst
index 3e5a9dc032..9b0eaba6e5 100644
--- a/docs/tools/qemu-storage-daemon.rst
+++ b/docs/tools/qemu-storage-daemon.rst
@@ -201,7 +201,7 @@ Export raw image file ``disk.img`` over NBD UNIX domain socket ``nbd.sock``::
--nbd-server addr.type=unix,addr.path=nbd.sock \
--export type=nbd,id=export,node-name=disk,writable=on
-Export a qcow2 image file ``disk.qcow2`` as a vhosts-user-blk device over UNIX
+Export a qcow2 image file ``disk.qcow2`` as a vhost-user-blk device over UNIX
domain socket ``vhost-user-blk.sock``::
$ qemu-storage-daemon \
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index 2b55d52150..5f8a878f20 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -581,7 +581,7 @@ static void intel_hda_set_st_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint3
if (st->ctl & 0x01) {
/* reset */
dprint(d, 1, "st #%d: reset\n", reg->stream);
- st->ctl = SD_STS_FIFO_READY << 24;
+ st->ctl = SD_STS_FIFO_READY << 24 | SD_CTL_STREAM_RESET;
}
if ((st->ctl & 0x02) != (old & 0x02)) {
uint32_t stnr = (st->ctl >> 20) & 0x0f;
diff --git a/hw/block/block.c b/hw/block/block.c
index d47ebf005a..25f45df723 100644
--- a/hw/block/block.c
+++ b/hw/block/block.c
@@ -171,8 +171,7 @@ bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
perm |= BLK_PERM_WRITE;
}
- shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
- BLK_PERM_GRAPH_MOD;
+ shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED;
if (resizable) {
shared_perm |= BLK_PERM_RESIZE;
}
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index ee5a5352dc..49276e46f2 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -154,17 +154,6 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
g_free(s);
}
-static bool virtio_blk_data_plane_handle_output(VirtIODevice *vdev,
- VirtQueue *vq)
-{
- VirtIOBlock *s = (VirtIOBlock *)vdev;
-
- assert(s->dataplane);
- assert(s->dataplane_started);
-
- return virtio_blk_handle_vq(s, vq);
-}
-
/* Context: QEMU global mutex held */
int virtio_blk_data_plane_start(VirtIODevice *vdev)
{
@@ -258,8 +247,7 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
for (i = 0; i < nvqs; i++) {
VirtQueue *vq = virtio_get_queue(s->vdev, i);
- virtio_queue_aio_set_host_notifier_handler(vq, s->ctx,
- virtio_blk_data_plane_handle_output);
+ virtio_queue_aio_attach_host_notifier(vq, s->ctx);
}
aio_context_release(s->ctx);
return 0;
@@ -302,7 +290,7 @@ static void virtio_blk_data_plane_stop_bh(void *opaque)
for (i = 0; i < s->conf->num_queues; i++) {
VirtQueue *vq = virtio_get_queue(s->vdev, i);
- virtio_queue_aio_set_host_notifier_handler(vq, s->ctx, NULL);
+ virtio_queue_aio_detach_host_notifier(vq, s->ctx);
}
}
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index f139cd7cc9..82676cdd01 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -767,12 +767,11 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
return 0;
}
-bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
+void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
{
VirtIOBlockReq *req;
MultiReqBuffer mrb = {};
bool suppress_notifications = virtio_queue_get_notification(vq);
- bool progress = false;
aio_context_acquire(blk_get_aio_context(s->blk));
blk_io_plug(s->blk);
@@ -783,7 +782,6 @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
}
while ((req = virtio_blk_get_request(s, vq))) {
- progress = true;
if (virtio_blk_handle_request(req, &mrb)) {
virtqueue_detach_element(req->vq, &req->elem, 0);
virtio_blk_free_request(req);
@@ -802,19 +800,13 @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
blk_io_unplug(s->blk);
aio_context_release(blk_get_aio_context(s->blk));
- return progress;
-}
-
-static void virtio_blk_handle_output_do(VirtIOBlock *s, VirtQueue *vq)
-{
- virtio_blk_handle_vq(s, vq);
}
static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOBlock *s = (VirtIOBlock *)vdev;
- if (s->dataplane) {
+ if (s->dataplane && !s->dataplane_started) {
/* Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start
* dataplane here instead of waiting for .set_status().
*/
@@ -823,7 +815,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
return;
}
}
- virtio_blk_handle_output_do(s, vq);
+ virtio_blk_handle_vq(s, vq);
}
void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh)
diff --git a/hw/display/Kconfig b/hw/display/Kconfig
index a2306b67d8..a1b159becd 100644
--- a/hw/display/Kconfig
+++ b/hw/display/Kconfig
@@ -49,7 +49,7 @@ config VGA_ISA
depends on ISA_BUS
select VGA
-config VGA_ISA_MM
+config VGA_MMIO
bool
select VGA
diff --git a/hw/display/edid-generate.c b/hw/display/edid-generate.c
index f2b874d5e3..bccf32af69 100644
--- a/hw/display/edid-generate.c
+++ b/hw/display/edid-generate.c
@@ -24,6 +24,9 @@ static const struct edid_mode {
{ .xres = 2048, .yres = 1152 },
{ .xres = 1920, .yres = 1080, .dta = 31 },
+ /* dea/dta extension timings (all @ 60 Hz) */
+ { .xres = 3840, .yres = 2160, .dta = 97 },
+
/* additional standard timings 3 (all @ 60Hz) */
{ .xres = 1920, .yres = 1200, .xtra3 = 10, .bit = 0 },
{ .xres = 1600, .yres = 1200, .xtra3 = 9, .bit = 2 },
@@ -401,10 +404,10 @@ void qemu_edid_generate(uint8_t *edid, size_t size,
info->name = "QEMU Monitor";
}
if (!info->prefx) {
- info->prefx = 1024;
+ info->prefx = 1280;
}
if (!info->prefy) {
- info->prefy = 768;
+ info->prefy = 800;
}
if (info->prefx >= 4096 || info->prefy >= 4096) {
large_screen = 1;
diff --git a/hw/display/macfb.c b/hw/display/macfb.c
index 277d3e6633..4bd7c3ad6a 100644
--- a/hw/display/macfb.c
+++ b/hw/display/macfb.c
@@ -661,9 +661,9 @@ static bool macfb_common_realize(DeviceState *dev, MacfbState *s, Error **errp)
memory_region_init_ram(&s->mem_vram, OBJECT(dev), "macfb-vram",
MACFB_VRAM_SIZE, &error_abort);
+ memory_region_set_log(&s->mem_vram, true, DIRTY_MEMORY_VGA);
s->vram = memory_region_get_ram_ptr(&s->mem_vram);
s->vram_bit_mask = MACFB_VRAM_SIZE - 1;
- memory_region_set_coalescing(&s->mem_vram);
s->vbl_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, macfb_vbl_timer, s);
macfb_update_mode(s);
diff --git a/hw/display/meson.build b/hw/display/meson.build
index 861c43ff98..adc53dd8b6 100644
--- a/hw/display/meson.build
+++ b/hw/display/meson.build
@@ -18,7 +18,7 @@ softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xenfb.c'))
softmmu_ss.add(when: 'CONFIG_VGA_PCI', if_true: files('vga-pci.c'))
softmmu_ss.add(when: 'CONFIG_VGA_ISA', if_true: files('vga-isa.c'))
-softmmu_ss.add(when: 'CONFIG_VGA_ISA_MM', if_true: files('vga-isa-mm.c'))
+softmmu_ss.add(when: 'CONFIG_VGA_MMIO', if_true: files('vga-mmio.c'))
softmmu_ss.add(when: 'CONFIG_VMWARE_VGA', if_true: files('vmware_vga.c'))
softmmu_ss.add(when: 'CONFIG_BOCHS_DISPLAY', if_true: files('bochs-display.c'))
diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-isa-mm.c
deleted file mode 100644
index 7321b7a06d..0000000000
--- a/hw/display/vga-isa-mm.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * QEMU ISA MM VGA Emulator.
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/bitops.h"
-#include "qemu/units.h"
-#include "migration/vmstate.h"
-#include "hw/display/vga.h"
-#include "vga_int.h"
-#include "ui/pixel_ops.h"
-
-#define VGA_RAM_SIZE (8 * MiB)
-
-typedef struct ISAVGAMMState {
- VGACommonState vga;
- int it_shift;
-} ISAVGAMMState;
-
-/* Memory mapped interface */
-static uint64_t vga_mm_read(void *opaque, hwaddr addr, unsigned size)
-{
- ISAVGAMMState *s = opaque;
-
- return vga_ioport_read(&s->vga, addr >> s->it_shift) &
- MAKE_64BIT_MASK(0, size * 8);
-}
-
-static void vga_mm_write(void *opaque, hwaddr addr, uint64_t value,
- unsigned size)
-{
- ISAVGAMMState *s = opaque;
-
- vga_ioport_write(&s->vga, addr >> s->it_shift,
- value & MAKE_64BIT_MASK(0, size * 8));
-}
-
-static const MemoryRegionOps vga_mm_ctrl_ops = {
- .read = vga_mm_read,
- .write = vga_mm_write,
- .valid.min_access_size = 1,
- .valid.max_access_size = 4,
- .impl.min_access_size = 1,
- .impl.max_access_size = 4,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void vga_mm_init(ISAVGAMMState *s, hwaddr vram_base,
- hwaddr ctrl_base, int it_shift,
- MemoryRegion *address_space)
-{
- MemoryRegion *s_ioport_ctrl, *vga_io_memory;
-
- s->it_shift = it_shift;
- s_ioport_ctrl = g_malloc(sizeof(*s_ioport_ctrl));
- memory_region_init_io(s_ioport_ctrl, NULL, &vga_mm_ctrl_ops, s,
- "vga-mm-ctrl", 0x100000);
- memory_region_set_flush_coalesced(s_ioport_ctrl);
-
- vga_io_memory = g_malloc(sizeof(*vga_io_memory));
- /* XXX: endianness? */
- memory_region_init_io(vga_io_memory, NULL, &vga_mem_ops, &s->vga,
- "vga-mem", 0x20000);
-
- vmstate_register(NULL, 0, &vmstate_vga_common, s);
-
- memory_region_add_subregion(address_space, ctrl_base, s_ioport_ctrl);
- s->vga.bank_offset = 0;
- memory_region_add_subregion(address_space,
- vram_base + 0x000a0000, vga_io_memory);
- memory_region_set_coalescing(vga_io_memory);
-}
-
-int isa_vga_mm_init(hwaddr vram_base,
- hwaddr ctrl_base, int it_shift,
- MemoryRegion *address_space)
-{
- ISAVGAMMState *s;
-
- s = g_malloc0(sizeof(*s));
-
- s->vga.vram_size_mb = VGA_RAM_SIZE / MiB;
- s->vga.global_vmstate = true;
- vga_common_init(&s->vga, NULL);
- vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
-
- s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s);
-
- memory_region_add_subregion(address_space,
- VBE_DISPI_LFB_PHYSICAL_ADDRESS,
- &s->vga.vram);
-
- return 0;
-}
diff --git a/hw/display/vga-mmio.c b/hw/display/vga-mmio.c
new file mode 100644
index 0000000000..4969368081
--- /dev/null
+++ b/hw/display/vga-mmio.c
@@ -0,0 +1,139 @@
+/*
+ * QEMU MMIO VGA Emulator.
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "hw/display/vga.h"
+#include "hw/qdev-properties.h"
+#include "vga_int.h"
+
+/*
+ * QEMU interface:
+ * + sysbus MMIO region 0: VGA I/O registers
+ * + sysbus MMIO region 1: VGA MMIO registers
+ * + sysbus MMIO region 2: VGA memory
+ */
+
+OBJECT_DECLARE_SIMPLE_TYPE(VGAMmioState, VGA_MMIO)
+
+struct VGAMmioState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ VGACommonState vga;
+ MemoryRegion iomem;
+ MemoryRegion lowmem;
+
+ uint8_t it_shift;
+};
+
+static uint64_t vga_mm_read(void *opaque, hwaddr addr, unsigned size)
+{
+ VGAMmioState *s = opaque;
+
+ return vga_ioport_read(&s->vga, addr >> s->it_shift) &
+ MAKE_64BIT_MASK(0, size * 8);
+}
+
+static void vga_mm_write(void *opaque, hwaddr addr, uint64_t value,
+ unsigned size)
+{
+ VGAMmioState *s = opaque;
+
+ vga_ioport_write(&s->vga, addr >> s->it_shift,
+ value & MAKE_64BIT_MASK(0, size * 8));
+}
+
+static const MemoryRegionOps vga_mm_ctrl_ops = {
+ .read = vga_mm_read,
+ .write = vga_mm_write,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 4,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void vga_mmio_reset(DeviceState *dev)
+{
+ VGAMmioState *s = VGA_MMIO(dev);
+
+ vga_common_reset(&s->vga);
+}
+
+static void vga_mmio_realizefn(DeviceState *dev, Error **errp)
+{
+ VGAMmioState *s = VGA_MMIO(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(dev), &vga_mm_ctrl_ops, s,
+ "vga-mmio", 0x100000);
+ memory_region_set_flush_coalesced(&s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
+
+ /* XXX: endianness? */
+ memory_region_init_io(&s->lowmem, OBJECT(dev), &vga_mem_ops, &s->vga,
+ "vga-lowmem", 0x20000);
+ memory_region_set_coalescing(&s->lowmem);
+ sysbus_init_mmio(sbd, &s->lowmem);
+
+ s->vga.bank_offset = 0;
+ s->vga.global_vmstate = true;
+ vga_common_init(&s->vga, OBJECT(dev));
+ sysbus_init_mmio(sbd, &s->vga.vram);
+ s->vga.con = graphic_console_init(dev, 0, s->vga.hw_ops, &s->vga);
+}
+
+static Property vga_mmio_properties[] = {
+ DEFINE_PROP_UINT8("it_shift", VGAMmioState, it_shift, 0),
+ DEFINE_PROP_UINT32("vgamem_mb", VGAMmioState, vga.vram_size_mb, 8),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vga_mmio_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = vga_mmio_realizefn;
+ dc->reset = vga_mmio_reset;
+ dc->vmsd = &vmstate_vga_common;
+ device_class_set_props(dc, vga_mmio_properties);
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+}
+
+static const TypeInfo vga_mmio_info = {
+ .name = TYPE_VGA_MMIO,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(VGAMmioState),
+ .class_init = vga_mmio_class_initfn,
+};
+
+static void vga_mmio_register_types(void)
+{
+ type_register_static(&vga_mmio_info);
+}
+
+type_init(vga_mmio_register_types)
diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index d4a440e815..09818231bd 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -485,9 +485,6 @@ vhost_user_gpu_guest_notifier_pending(VirtIODevice *vdev, int idx)
{
VhostUserGPU *g = VHOST_USER_GPU(vdev);
- if (idx == VIRTIO_CONFIG_IRQ_IDX) {
- return false;
- }
return vhost_virtqueue_pending(&g->vhost->dev, idx);
}
@@ -496,9 +493,6 @@ vhost_user_gpu_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
{
VhostUserGPU *g = VHOST_USER_GPU(vdev);
- if (idx == VIRTIO_CONFIG_IRQ_IDX) {
- return;
- }
vhost_virtqueue_mask(&g->vhost->dev, vdev, idx, mask);
}
diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index 9376a8f4ce..6236711e1b 100644
--- a/hw/input/ps2.c
+++ b/hw/input/ps2.c
@@ -123,6 +123,7 @@ typedef struct {
int mouse_dx; /* current values, needed for 'poll' mode */
int mouse_dy;
int mouse_dz;
+ int mouse_dw;
uint8_t mouse_buttons;
} PS2MouseState;
@@ -715,7 +716,7 @@ static int ps2_mouse_send_packet(PS2MouseState *s)
/* IMPS/2 and IMEX send 4 bytes, PS2 sends 3 bytes */
const int needed = s->mouse_type ? 4 : 3;
unsigned int b;
- int dx1, dy1, dz1;
+ int dx1, dy1, dz1, dw1;
if (PS2_QUEUE_SIZE - s->common.queue.count < needed) {
return 0;
@@ -724,6 +725,7 @@ static int ps2_mouse_send_packet(PS2MouseState *s)
dx1 = s->mouse_dx;
dy1 = s->mouse_dy;
dz1 = s->mouse_dz;
+ dw1 = s->mouse_dw;
/* XXX: increase range to 8 bits ? */
if (dx1 > 127)
dx1 = 127;
@@ -740,6 +742,9 @@ static int ps2_mouse_send_packet(PS2MouseState *s)
/* extra byte for IMPS/2 or IMEX */
switch(s->mouse_type) {
default:
+ /* Just ignore the wheels if not supported */
+ s->mouse_dz = 0;
+ s->mouse_dw = 0;
break;
case 3:
if (dz1 > 127)
@@ -747,13 +752,41 @@ static int ps2_mouse_send_packet(PS2MouseState *s)
else if (dz1 < -127)
dz1 = -127;
ps2_queue_noirq(&s->common, dz1 & 0xff);
+ s->mouse_dz -= dz1;
+ s->mouse_dw = 0;
break;
case 4:
- if (dz1 > 7)
- dz1 = 7;
- else if (dz1 < -7)
- dz1 = -7;
- b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
+ /*
+ * This matches what the Linux kernel expects for exps/2 in
+ * drivers/input/mouse/psmouse-base.c. Note, if you happen to
+ * press/release the 4th or 5th buttons at the same moment as a
+ * horizontal wheel scroll, those button presses will get lost. I'm not
+ * sure what to do about that, since by this point we don't know
+ * whether those buttons actually changed state.
+ */
+ if (dw1 != 0) {
+ if (dw1 > 31) {
+ dw1 = 31;
+ } else if (dw1 < -31) {
+ dw1 = -31;
+ }
+
+ /*
+ * linux kernel expects first 6 bits to represent the value
+ * for horizontal scroll
+ */
+ b = (dw1 & 0x3f) | 0x40;
+ s->mouse_dw -= dw1;
+ } else {
+ if (dz1 > 7) {
+ dz1 = 7;
+ } else if (dz1 < -7) {
+ dz1 = -7;
+ }
+
+ b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
+ s->mouse_dz -= dz1;
+ }
ps2_queue_noirq(&s->common, b);
break;
}
@@ -764,7 +797,6 @@ static int ps2_mouse_send_packet(PS2MouseState *s)
/* update deltas */
s->mouse_dx -= dx1;
s->mouse_dy -= dy1;
- s->mouse_dz -= dz1;
return 1;
}
@@ -806,6 +838,12 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
} else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
s->mouse_dz++;
}
+
+ if (btn->button == INPUT_BUTTON_WHEEL_RIGHT) {
+ s->mouse_dw--;
+ } else if (btn->button == INPUT_BUTTON_WHEEL_LEFT) {
+ s->mouse_dw++;
+ }
} else {
s->mouse_buttons &= ~bmap[btn->button];
}
@@ -833,8 +871,10 @@ static void ps2_mouse_sync(DeviceState *dev)
/* if not remote, send event. Multiple events are sent if
too big deltas */
while (ps2_mouse_send_packet(s)) {
- if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
+ if (s->mouse_dx == 0 && s->mouse_dy == 0
+ && s->mouse_dz == 0 && s->mouse_dw == 0) {
break;
+ }
}
}
}
@@ -1036,6 +1076,7 @@ static void ps2_mouse_reset(void *opaque)
s->mouse_dx = 0;
s->mouse_dy = 0;
s->mouse_dz = 0;
+ s->mouse_dw = 0;
s->mouse_buttons = 0;
}
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index e4c7c9b88a..55dfe5036f 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -672,12 +672,13 @@ static void q800_init(MachineState *machine)
/* Remove qtest_enabled() check once firmware files are in the tree */
if (!qtest_enabled()) {
- if (bios_size < 0 || bios_size > MACROM_SIZE) {
+ if (bios_size <= 0 || bios_size > MACROM_SIZE) {
error_report("could not load MacROM '%s'", bios_name);
exit(1);
}
- ptr = rom_ptr(MACROM_ADDR, MACROM_SIZE);
+ ptr = rom_ptr(MACROM_ADDR, bios_size);
+ assert(ptr != NULL);
stl_phys(cs->as, 0, ldl_p(ptr)); /* reset initial SP */
stl_phys(cs->as, 4,
MACROM_ADDR + ldl_p(ptr + 4)); /* reset initial PC */
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index 0efa4a45c7..78e926a554 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -304,10 +304,17 @@ type_init(virt_machine_register_types)
} \
type_init(machvirt_machine_##major##_##minor##_init);
+static void virt_machine_7_0_options(MachineClass *mc)
+{
+}
+DEFINE_VIRT_MACHINE(7, 0, true)
+
static void virt_machine_6_2_options(MachineClass *mc)
{
+ virt_machine_7_0_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_6_2, hw_compat_6_2_len);
}
-DEFINE_VIRT_MACHINE(6, 2, true)
+DEFINE_VIRT_MACHINE(6, 2, false)
static void virt_machine_6_1_options(MachineClass *mc)
{
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index b4c5549ce8..725525358d 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -16,7 +16,7 @@ config JAZZ
select I8254
select I8257
select PCSPK
- select VGA_ISA_MM
+ select VGA_MMIO
select G364FB
select DP8393X
select ESP
diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c
index f5a26e174d..44f0d48bfd 100644
--- a/hw/mips/jazz.c
+++ b/hw/mips/jazz.c
@@ -43,6 +43,7 @@
#include "hw/rtc/mc146818rtc.h"
#include "hw/timer/i8254.h"
#include "hw/display/vga.h"
+#include "hw/display/bochs-vbe.h"
#include "hw/audio/pcspk.h"
#include "hw/input/i8042.h"
#include "hw/sysbus.h"
@@ -274,7 +275,13 @@ static void mips_jazz_init(MachineState *machine,
}
break;
case JAZZ_PICA61:
- isa_vga_mm_init(0x40000000, 0x60000000, 0, get_system_memory());
+ dev = qdev_new(TYPE_VGA_MMIO);
+ qdev_prop_set_uint8(dev, "it_shift", 0);
+ sysbus = SYS_BUS_DEVICE(dev);
+ sysbus_realize_and_unref(sysbus, &error_fatal);
+ sysbus_mmio_map(sysbus, 0, 0x60000000);
+ sysbus_mmio_map(sysbus, 1, 0x400a0000);
+ sysbus_mmio_map(sysbus, 2, VBE_DISPI_LFB_PHYSICAL_ADDRESS);
break;
default:
break;
diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c
index 126ee35b70..89d71cfb8e 100644
--- a/hw/net/vhost_net-stub.c
+++ b/hw/net/vhost_net-stub.c
@@ -101,12 +101,3 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
{
return 0;
}
-
-bool vhost_net_config_pending(VHostNetState *net)
-{
- return false;
-}
-
-void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask)
-{
-}
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 9c9fd0a73f..30379d2ca4 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -457,15 +457,6 @@ void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
vhost_virtqueue_mask(&net->dev, dev, idx, mask);
}
-bool vhost_net_config_pending(VHostNetState *net)
-{
- return vhost_config_pending(&net->dev);
-}
-
-void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask)
-{
- vhost_config_mask(&net->dev, dev, mask);
-}
VHostNetState *get_vhost_net(NetClientState *nc)
{
VHostNetState *vhost_net = 0;
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 5806a50c8d..cf8ab0f8af 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3168,9 +3168,6 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
VirtIONet *n = VIRTIO_NET(vdev);
NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
assert(n->vhost_started);
- if (idx == VIRTIO_CONFIG_IRQ_IDX) {
- return vhost_net_config_pending(get_vhost_net(nc->peer));
- }
return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx);
}
@@ -3180,11 +3177,8 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
VirtIONet *n = VIRTIO_NET(vdev);
NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
assert(n->vhost_started);
- if (idx == VIRTIO_CONFIG_IRQ_IDX) {
- vhost_net_config_mask(get_vhost_net(nc->peer), vdev, mask);
- return;
- }
- vhost_net_virtqueue_mask(get_vhost_net(nc->peer), vdev, idx, mask);
+ vhost_net_virtqueue_mask(get_vhost_net(nc->peer),
+ vdev, idx, mask);
}
static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features)
diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index c78084cce7..7fb35dc031 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -19,6 +19,7 @@
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "qom/object.h"
+#include "sysemu/sysemu.h"
#define phb3_error(phb, fmt, ...) \
qemu_log_mask(LOG_GUEST_ERROR, "phb3[%d:%d]: " fmt "\n", \
@@ -981,10 +982,6 @@ static void pnv_phb3_instance_init(Object *obj)
/* Power Bus Common Queue */
object_initialize_child(obj, "pbcq", &phb->pbcq, TYPE_PNV_PBCQ);
- /* Root Port */
- object_initialize_child(obj, "root", &phb->root, TYPE_PNV_PHB3_ROOT_PORT);
- qdev_prop_set_int32(DEVICE(&phb->root), "addr", PCI_DEVFN(0, 0));
- qdev_prop_set_bit(DEVICE(&phb->root), "multifunction", false);
}
static void pnv_phb3_realize(DeviceState *dev, Error **errp)
@@ -994,6 +991,30 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp)
PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
int i;
+ /* User created devices */
+ if (!phb->chip) {
+ Error *local_err = NULL;
+ BusState *s;
+
+ phb->chip = pnv_get_chip(pnv, phb->chip_id);
+ if (!phb->chip) {
+ error_setg(errp, "invalid chip id: %d", phb->chip_id);
+ return;
+ }
+
+ /*
+ * Reparent user created devices to the chip to build
+ * correctly the device tree.
+ */
+ pnv_chip_parent_fixup(phb->chip, OBJECT(phb), phb->phb_id);
+
+ s = qdev_get_parent_bus(DEVICE(phb->chip));
+ if (!qdev_set_parent_bus(DEVICE(phb), s, &local_err)) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
+
if (phb->phb_id >= PNV_CHIP_GET_CLASS(phb->chip)->num_phbs) {
error_setg(errp, "invalid PHB index: %d", phb->phb_id);
return;
@@ -1053,10 +1074,10 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp)
pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb);
- /* Add a single Root port */
- qdev_prop_set_uint8(DEVICE(&phb->root), "chassis", phb->chip_id);
- qdev_prop_set_uint16(DEVICE(&phb->root), "slot", phb->phb_id);
- qdev_realize(DEVICE(&phb->root), BUS(pci->bus), &error_fatal);
+ if (defaults_enabled()) {
+ pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb),
+ TYPE_PNV_PHB3_ROOT_PORT);
+ }
}
void pnv_phb3_update_regions(PnvPHB3 *phb)
@@ -1107,7 +1128,7 @@ static void pnv_phb3_class_init(ObjectClass *klass, void *data)
dc->realize = pnv_phb3_realize;
device_class_set_props(dc, pnv_phb3_properties);
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
- dc->user_creatable = false;
+ dc->user_creatable = true;
}
static const TypeInfo pnv_phb3_type_info = {
@@ -1142,8 +1163,24 @@ static const TypeInfo pnv_phb3_root_bus_info = {
static void pnv_phb3_root_port_realize(DeviceState *dev, Error **errp)
{
PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
+ PCIDevice *pci = PCI_DEVICE(dev);
+ PCIBus *bus = pci_get_bus(pci);
+ PnvPHB3 *phb = NULL;
Error *local_err = NULL;
+ phb = (PnvPHB3 *) object_dynamic_cast(OBJECT(bus->qbus.parent),
+ TYPE_PNV_PHB3);
+
+ if (!phb) {
+ error_setg(errp,
+"pnv_phb3_root_port devices must be connected to pnv-phb3 buses");
+ return;
+ }
+
+ /* Set unique chassis/slot values for the root port */
+ qdev_prop_set_uint8(&pci->qdev, "chassis", phb->chip_id);
+ qdev_prop_set_uint16(&pci->qdev, "slot", phb->phb_id);
+
rpc->parent_realize(dev, &local_err);
if (local_err) {
error_propagate(errp, local_err);
@@ -1161,7 +1198,7 @@ static void pnv_phb3_root_port_class_init(ObjectClass *klass, void *data)
device_class_set_parent_realize(dc, pnv_phb3_root_port_realize,
&rpc->parent_realize);
- dc->user_creatable = false;
+ dc->user_creatable = true;
k->vendor_id = PCI_VENDOR_ID_IBM;
k->device_id = 0x03dc;
diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 5ba26e250a..a7b638831e 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -22,12 +22,17 @@
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "qom/object.h"
+#include "sysemu/sysemu.h"
#include "trace.h"
#define phb_error(phb, fmt, ...) \
qemu_log_mask(LOG_GUEST_ERROR, "phb4[%d:%d]: " fmt "\n", \
(phb)->chip_id, (phb)->phb_id, ## __VA_ARGS__)
+#define phb_pec_error(pec, fmt, ...) \
+ qemu_log_mask(LOG_GUEST_ERROR, "phb4_pec[%d:%d]: " fmt "\n", \
+ (pec)->chip_id, (pec)->index, ## __VA_ARGS__)
+
/*
* QEMU version of the GETFIELD/SETFIELD macros
*
@@ -151,7 +156,10 @@ static void pnv_phb4_rc_config_write(PnvPHB4 *phb, unsigned off,
}
pdev = pci_find_device(pci->bus, 0, 0);
- assert(pdev);
+ if (!pdev) {
+ phb_error(phb, "rc_config_write device not found\n");
+ return;
+ }
pci_host_config_write_common(pdev, off, PHB_RC_CONFIG_SIZE,
bswap32(val), 4);
@@ -170,7 +178,10 @@ static uint64_t pnv_phb4_rc_config_read(PnvPHB4 *phb, unsigned off,
}
pdev = pci_find_device(pci->bus, 0, 0);
- assert(pdev);
+ if (!pdev) {
+ phb_error(phb, "rc_config_read device not found\n");
+ return ~0ull;
+ }
val = pci_host_config_read_common(pdev, off, PHB_RC_CONFIG_SIZE, 4);
return bswap32(val);
@@ -847,6 +858,284 @@ const MemoryRegionOps pnv_phb4_xscom_ops = {
.endianness = DEVICE_BIG_ENDIAN,
};
+static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr,
+ unsigned size)
+{
+ PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
+ uint32_t reg = addr >> 3;
+
+ /* TODO: add list of allowed registers and error out if not */
+ return stack->nest_regs[reg];
+}
+
+static void pnv_phb4_update_regions(PnvPhb4PecStack *stack)
+{
+ PnvPHB4 *phb = stack->phb;
+
+ /* Unmap first always */
+ if (memory_region_is_mapped(&phb->mr_regs)) {
+ memory_region_del_subregion(&stack->phbbar, &phb->mr_regs);
+ }
+ if (memory_region_is_mapped(&phb->xsrc.esb_mmio)) {
+ memory_region_del_subregion(&stack->intbar, &phb->xsrc.esb_mmio);
+ }
+
+ /* Map registers if enabled */
+ if (memory_region_is_mapped(&stack->phbbar)) {
+ memory_region_add_subregion(&stack->phbbar, 0, &phb->mr_regs);
+ }
+
+ /* Map ESB if enabled */
+ if (memory_region_is_mapped(&stack->intbar)) {
+ memory_region_add_subregion(&stack->intbar, 0, &phb->xsrc.esb_mmio);
+ }
+
+ /* Check/update m32 */
+ pnv_phb4_check_all_mbt(phb);
+}
+
+static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack)
+{
+ PnvPhb4PecState *pec = stack->pec;
+ MemoryRegion *sysmem = get_system_memory();
+ uint64_t bar_en = stack->nest_regs[PEC_NEST_STK_BAR_EN];
+ uint64_t bar, mask, size;
+ char name[64];
+
+ /*
+ * NOTE: This will really not work well if those are remapped
+ * after the PHB has created its sub regions. We could do better
+ * if we had a way to resize regions but we don't really care
+ * that much in practice as the stuff below really only happens
+ * once early during boot
+ */
+
+ /* Handle unmaps */
+ if (memory_region_is_mapped(&stack->mmbar0) &&
+ !(bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) {
+ memory_region_del_subregion(sysmem, &stack->mmbar0);
+ }
+ if (memory_region_is_mapped(&stack->mmbar1) &&
+ !(bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) {
+ memory_region_del_subregion(sysmem, &stack->mmbar1);
+ }
+ if (memory_region_is_mapped(&stack->phbbar) &&
+ !(bar_en & PEC_NEST_STK_BAR_EN_PHB)) {
+ memory_region_del_subregion(sysmem, &stack->phbbar);
+ }
+ if (memory_region_is_mapped(&stack->intbar) &&
+ !(bar_en & PEC_NEST_STK_BAR_EN_INT)) {
+ memory_region_del_subregion(sysmem, &stack->intbar);
+ }
+
+ /* Update PHB */
+ pnv_phb4_update_regions(stack);
+
+ /* Handle maps */
+ if (!memory_region_is_mapped(&stack->mmbar0) &&
+ (bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) {
+ bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0] >> 8;
+ mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0_MASK];
+ size = ((~mask) >> 8) + 1;
+ snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio0",
+ pec->chip_id, pec->index, stack->stack_no);
+ memory_region_init(&stack->mmbar0, OBJECT(stack), name, size);
+ memory_region_add_subregion(sysmem, bar, &stack->mmbar0);
+ stack->mmio0_base = bar;
+ stack->mmio0_size = size;
+ }
+ if (!memory_region_is_mapped(&stack->mmbar1) &&
+ (bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) {
+ bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1] >> 8;
+ mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1_MASK];
+ size = ((~mask) >> 8) + 1;
+ snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio1",
+ pec->chip_id, pec->index, stack->stack_no);
+ memory_region_init(&stack->mmbar1, OBJECT(stack), name, size);
+ memory_region_add_subregion(sysmem, bar, &stack->mmbar1);
+ stack->mmio1_base = bar;
+ stack->mmio1_size = size;
+ }
+ if (!memory_region_is_mapped(&stack->phbbar) &&
+ (bar_en & PEC_NEST_STK_BAR_EN_PHB)) {
+ bar = stack->nest_regs[PEC_NEST_STK_PHB_REGS_BAR] >> 8;
+ size = PNV_PHB4_NUM_REGS << 3;
+ snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-phb",
+ pec->chip_id, pec->index, stack->stack_no);
+ memory_region_init(&stack->phbbar, OBJECT(stack), name, size);
+ memory_region_add_subregion(sysmem, bar, &stack->phbbar);
+ }
+ if (!memory_region_is_mapped(&stack->intbar) &&
+ (bar_en & PEC_NEST_STK_BAR_EN_INT)) {
+ bar = stack->nest_regs[PEC_NEST_STK_INT_BAR] >> 8;
+ size = PNV_PHB4_MAX_INTs << 16;
+ snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-int",
+ stack->pec->chip_id, stack->pec->index, stack->stack_no);
+ memory_region_init(&stack->intbar, OBJECT(stack), name, size);
+ memory_region_add_subregion(sysmem, bar, &stack->intbar);
+ }
+
+ /* Update PHB */
+ pnv_phb4_update_regions(stack);
+}
+
+static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+ PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
+ PnvPhb4PecState *pec = stack->pec;
+ uint32_t reg = addr >> 3;
+
+ switch (reg) {
+ case PEC_NEST_STK_PCI_NEST_FIR:
+ stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] = val;
+ break;
+ case PEC_NEST_STK_PCI_NEST_FIR_CLR:
+ stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] &= val;
+ break;
+ case PEC_NEST_STK_PCI_NEST_FIR_SET:
+ stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] |= val;
+ break;
+ case PEC_NEST_STK_PCI_NEST_FIR_MSK:
+ stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] = val;
+ break;
+ case PEC_NEST_STK_PCI_NEST_FIR_MSKC:
+ stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] &= val;
+ break;
+ case PEC_NEST_STK_PCI_NEST_FIR_MSKS:
+ stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] |= val;
+ break;
+ case PEC_NEST_STK_PCI_NEST_FIR_ACT0:
+ case PEC_NEST_STK_PCI_NEST_FIR_ACT1:
+ stack->nest_regs[reg] = val;
+ break;
+ case PEC_NEST_STK_PCI_NEST_FIR_WOF:
+ stack->nest_regs[reg] = 0;
+ break;
+ case PEC_NEST_STK_ERR_REPORT_0:
+ case PEC_NEST_STK_ERR_REPORT_1:
+ case PEC_NEST_STK_PBCQ_GNRL_STATUS:
+ /* Flag error ? */
+ break;
+ case PEC_NEST_STK_PBCQ_MODE:
+ stack->nest_regs[reg] = val & 0xff00000000000000ull;
+ break;
+ case PEC_NEST_STK_MMIO_BAR0:
+ case PEC_NEST_STK_MMIO_BAR0_MASK:
+ case PEC_NEST_STK_MMIO_BAR1:
+ case PEC_NEST_STK_MMIO_BAR1_MASK:
+ if (stack->nest_regs[PEC_NEST_STK_BAR_EN] &
+ (PEC_NEST_STK_BAR_EN_MMIO0 |
+ PEC_NEST_STK_BAR_EN_MMIO1)) {
+ phb_pec_error(pec, "Changing enabled BAR unsupported\n");
+ }
+ stack->nest_regs[reg] = val & 0xffffffffff000000ull;
+ break;
+ case PEC_NEST_STK_PHB_REGS_BAR:
+ if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_PHB) {
+ phb_pec_error(pec, "Changing enabled BAR unsupported\n");
+ }
+ stack->nest_regs[reg] = val & 0xffffffffffc00000ull;
+ break;
+ case PEC_NEST_STK_INT_BAR:
+ if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_INT) {
+ phb_pec_error(pec, "Changing enabled BAR unsupported\n");
+ }
+ stack->nest_regs[reg] = val & 0xfffffff000000000ull;
+ break;
+ case PEC_NEST_STK_BAR_EN:
+ stack->nest_regs[reg] = val & 0xf000000000000000ull;
+ pnv_pec_stk_update_map(stack);
+ break;
+ case PEC_NEST_STK_DATA_FRZ_TYPE:
+ case PEC_NEST_STK_PBCQ_TUN_BAR:
+ /* Not used for now */
+ stack->nest_regs[reg] = val;
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "phb4_pec: nest_xscom_write 0x%"HWADDR_PRIx
+ "=%"PRIx64"\n", addr, val);
+ }
+}
+
+static const MemoryRegionOps pnv_pec_stk_nest_xscom_ops = {
+ .read = pnv_pec_stk_nest_xscom_read,
+ .write = pnv_pec_stk_nest_xscom_write,
+ .valid.min_access_size = 8,
+ .valid.max_access_size = 8,
+ .impl.min_access_size = 8,
+ .impl.max_access_size = 8,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static uint64_t pnv_pec_stk_pci_xscom_read(void *opaque, hwaddr addr,
+ unsigned size)
+{
+ PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
+ uint32_t reg = addr >> 3;
+
+ /* TODO: add list of allowed registers and error out if not */
+ return stack->pci_regs[reg];
+}
+
+static void pnv_pec_stk_pci_xscom_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+ PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
+ uint32_t reg = addr >> 3;
+
+ switch (reg) {
+ case PEC_PCI_STK_PCI_FIR:
+ stack->pci_regs[reg] = val;
+ break;
+ case PEC_PCI_STK_PCI_FIR_CLR:
+ stack->pci_regs[PEC_PCI_STK_PCI_FIR] &= val;
+ break;
+ case PEC_PCI_STK_PCI_FIR_SET:
+ stack->pci_regs[PEC_PCI_STK_PCI_FIR] |= val;
+ break;
+ case PEC_PCI_STK_PCI_FIR_MSK:
+ stack->pci_regs[reg] = val;
+ break;
+ case PEC_PCI_STK_PCI_FIR_MSKC:
+ stack->pci_regs[PEC_PCI_STK_PCI_FIR_MSK] &= val;
+ break;
+ case PEC_PCI_STK_PCI_FIR_MSKS:
+ stack->pci_regs[PEC_PCI_STK_PCI_FIR_MSK] |= val;
+ break;
+ case PEC_PCI_STK_PCI_FIR_ACT0:
+ case PEC_PCI_STK_PCI_FIR_ACT1:
+ stack->pci_regs[reg] = val;
+ break;
+ case PEC_PCI_STK_PCI_FIR_WOF:
+ stack->pci_regs[reg] = 0;
+ break;
+ case PEC_PCI_STK_ETU_RESET:
+ stack->pci_regs[reg] = val & 0x8000000000000000ull;
+ /* TODO: Implement reset */
+ break;
+ case PEC_PCI_STK_PBAIB_ERR_REPORT:
+ break;
+ case PEC_PCI_STK_PBAIB_TX_CMD_CRED:
+ case PEC_PCI_STK_PBAIB_TX_DAT_CRED:
+ stack->pci_regs[reg] = val;
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "phb4_pec_stk: pci_xscom_write 0x%"HWADDR_PRIx
+ "=%"PRIx64"\n", addr, val);
+ }
+}
+
+static const MemoryRegionOps pnv_pec_stk_pci_xscom_ops = {
+ .read = pnv_pec_stk_pci_xscom_read,
+ .write = pnv_pec_stk_pci_xscom_write,
+ .valid.min_access_size = 8,
+ .valid.max_access_size = 8,
+ .impl.min_access_size = 8,
+ .impl.max_access_size = 8,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
static int pnv_phb4_map_irq(PCIDevice *pci_dev, int irq_num)
{
/* Check that out properly ... */
@@ -1063,6 +1352,23 @@ static const TypeInfo pnv_phb4_iommu_memory_region_info = {
};
/*
+ * Return the index/phb-id of a PHB4 that belongs to a
+ * pec->stacks[stack_index] stack.
+ */
+int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index)
+{
+ PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
+ int index = pec->index;
+ int offset = 0;
+
+ while (index--) {
+ offset += pecc->num_stacks[index];
+ }
+
+ return offset + stack_index;
+}
+
+/*
* MSI/MSIX memory region implementation.
* The handler handles both MSI and MSIX.
*/
@@ -1151,6 +1457,52 @@ static AddressSpace *pnv_phb4_dma_iommu(PCIBus *bus, void *opaque, int devfn)
return &ds->dma_as;
}
+static void pnv_phb4_xscom_realize(PnvPHB4 *phb)
+{
+ PnvPhb4PecStack *stack = phb->stack;
+ PnvPhb4PecState *pec = stack->pec;
+ PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
+ uint32_t pec_nest_base;
+ uint32_t pec_pci_base;
+ char name[64];
+
+ assert(pec);
+
+ /* Initialize the XSCOM regions for the stack registers */
+ snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest-stack-%d",
+ pec->chip_id, pec->index, stack->stack_no);
+ pnv_xscom_region_init(&stack->nest_regs_mr, OBJECT(stack),
+ &pnv_pec_stk_nest_xscom_ops, stack, name,
+ PHB4_PEC_NEST_STK_REGS_COUNT);
+
+ snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d",
+ pec->chip_id, pec->index, stack->stack_no);
+ pnv_xscom_region_init(&stack->pci_regs_mr, OBJECT(stack),
+ &pnv_pec_stk_pci_xscom_ops, stack, name,
+ PHB4_PEC_PCI_STK_REGS_COUNT);
+
+ /* PHB pass-through */
+ snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d-phb",
+ pec->chip_id, pec->index, stack->stack_no);
+ pnv_xscom_region_init(&stack->phb_regs_mr, OBJECT(phb),
+ &pnv_phb4_xscom_ops, phb, name, 0x40);
+
+ pec_nest_base = pecc->xscom_nest_base(pec);
+ pec_pci_base = pecc->xscom_pci_base(pec);
+
+ /* Populate the XSCOM address space. */
+ pnv_xscom_add_subregion(pec->chip,
+ pec_nest_base + 0x40 * (stack->stack_no + 1),
+ &stack->nest_regs_mr);
+ pnv_xscom_add_subregion(pec->chip,
+ pec_pci_base + 0x40 * (stack->stack_no + 1),
+ &stack->pci_regs_mr);
+ pnv_xscom_add_subregion(pec->chip,
+ pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 +
+ 0x40 * stack->stack_no,
+ &stack->phb_regs_mr);
+}
+
static void pnv_phb4_instance_init(Object *obj)
{
PnvPHB4 *phb = PNV_PHB4(obj);
@@ -1159,12 +1511,35 @@ static void pnv_phb4_instance_init(Object *obj)
/* XIVE interrupt source object */
object_initialize_child(obj, "source", &phb->xsrc, TYPE_XIVE_SOURCE);
+}
- /* Root Port */
- object_initialize_child(obj, "root", &phb->root, TYPE_PNV_PHB4_ROOT_PORT);
+static PnvPhb4PecStack *pnv_phb4_get_stack(PnvChip *chip, PnvPHB4 *phb,
+ Error **errp)
+{
+ Pnv9Chip *chip9 = PNV9_CHIP(chip);
+ int chip_id = phb->chip_id;
+ int index = phb->phb_id;
+ int i, j;
+
+ for (i = 0; i < chip->num_pecs; i++) {
+ /*
+ * For each PEC, check the amount of stacks it supports
+ * and see if the given phb4 index matches a stack.
+ */
+ PnvPhb4PecState *pec = &chip9->pecs[i];
- qdev_prop_set_int32(DEVICE(&phb->root), "addr", PCI_DEVFN(0, 0));
- qdev_prop_set_bit(DEVICE(&phb->root), "multifunction", false);
+ for (j = 0; j < pec->num_stacks; j++) {
+ if (index == pnv_phb4_pec_get_phb_id(pec, j)) {
+ return &pec->stacks[j];
+ }
+ }
+ }
+
+ error_setg(errp,
+ "pnv-phb4 chip-id %d index %d didn't match any existing PEC",
+ chip_id, index);
+
+ return NULL;
}
static void pnv_phb4_realize(DeviceState *dev, Error **errp)
@@ -1172,10 +1547,51 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp)
PnvPHB4 *phb = PNV_PHB4(dev);
PCIHostState *pci = PCI_HOST_BRIDGE(dev);
XiveSource *xsrc = &phb->xsrc;
+ Error *local_err = NULL;
int nr_irqs;
char name[32];
- assert(phb->stack);
+ /* User created PHB */
+ if (!phb->stack) {
+ PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
+ PnvChip *chip = pnv_get_chip(pnv, phb->chip_id);
+ PnvPhb4PecClass *pecc;
+ BusState *s;
+
+ if (!chip) {
+ error_setg(errp, "invalid chip id: %d", phb->chip_id);
+ return;
+ }
+
+ phb->stack = pnv_phb4_get_stack(chip, phb, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ /* All other phb properties but 'version' are already set */
+ pecc = PNV_PHB4_PEC_GET_CLASS(phb->stack->pec);
+ object_property_set_int(OBJECT(phb), "version", pecc->version,
+ &error_fatal);
+
+ /*
+ * Assign stack->phb since pnv_phb4_update_regions() uses it
+ * to access the phb.
+ */
+ phb->stack->phb = phb;
+
+ /*
+ * Reparent user created devices to the chip to build
+ * correctly the device tree.
+ */
+ pnv_chip_parent_fixup(chip, OBJECT(phb), phb->phb_id);
+
+ s = qdev_get_parent_bus(DEVICE(chip));
+ if (!qdev_set_parent_bus(DEVICE(phb), s, &local_err)) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
/* Set the "big_phb" flag */
phb->big_phb = phb->phb_id == 0 || phb->phb_id == 3;
@@ -1208,10 +1624,11 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp)
pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb);
pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
- /* Add a single Root port */
- qdev_prop_set_uint8(DEVICE(&phb->root), "chassis", phb->chip_id);
- qdev_prop_set_uint16(DEVICE(&phb->root), "slot", phb->phb_id);
- qdev_realize(DEVICE(&phb->root), BUS(pci->bus), &error_fatal);
+ /* Add a single Root port if running with defaults */
+ if (defaults_enabled()) {
+ pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb),
+ TYPE_PNV_PHB4_ROOT_PORT);
+ }
/* Setup XIVE Source */
if (phb->big_phb) {
@@ -1228,6 +1645,8 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp)
pnv_phb4_update_xsrc(phb);
phb->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs);
+
+ pnv_phb4_xscom_realize(phb);
}
static const char *pnv_phb4_root_bus_path(PCIHostState *host_bridge,
@@ -1277,7 +1696,7 @@ static void pnv_phb4_class_init(ObjectClass *klass, void *data)
dc->realize = pnv_phb4_realize;
device_class_set_props(dc, pnv_phb4_properties);
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
- dc->user_creatable = false;
+ dc->user_creatable = true;
xfc->notify = pnv_phb4_xive_notify;
}
@@ -1338,8 +1757,23 @@ static void pnv_phb4_root_port_reset(DeviceState *dev)
static void pnv_phb4_root_port_realize(DeviceState *dev, Error **errp)
{
PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
+ PCIDevice *pci = PCI_DEVICE(dev);
+ PCIBus *bus = pci_get_bus(pci);
+ PnvPHB4 *phb = NULL;
Error *local_err = NULL;
+ phb = (PnvPHB4 *) object_dynamic_cast(OBJECT(bus->qbus.parent),
+ TYPE_PNV_PHB4);
+
+ if (!phb) {
+ error_setg(errp, "%s must be connected to pnv-phb4 buses", dev->id);
+ return;
+ }
+
+ /* Set unique chassis/slot values for the root port */
+ qdev_prop_set_uint8(&pci->qdev, "chassis", phb->chip_id);
+ qdev_prop_set_uint16(&pci->qdev, "slot", phb->phb_id);
+
rpc->parent_realize(dev, &local_err);
if (local_err) {
error_propagate(errp, local_err);
@@ -1354,7 +1788,7 @@ static void pnv_phb4_root_port_class_init(ObjectClass *klass, void *data)
PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass);
dc->desc = "IBM PHB4 PCIE Root Port";
- dc->user_creatable = false;
+ dc->user_creatable = true;
device_class_set_parent_realize(dc, pnv_phb4_root_port_realize,
&rpc->parent_realize);
@@ -1388,32 +1822,6 @@ static void pnv_phb4_register_types(void)
type_init(pnv_phb4_register_types);
-void pnv_phb4_update_regions(PnvPhb4PecStack *stack)
-{
- PnvPHB4 *phb = &stack->phb;
-
- /* Unmap first always */
- if (memory_region_is_mapped(&phb->mr_regs)) {
- memory_region_del_subregion(&stack->phbbar, &phb->mr_regs);
- }
- if (memory_region_is_mapped(&phb->xsrc.esb_mmio)) {
- memory_region_del_subregion(&stack->intbar, &phb->xsrc.esb_mmio);
- }
-
- /* Map registers if enabled */
- if (memory_region_is_mapped(&stack->phbbar)) {
- memory_region_add_subregion(&stack->phbbar, 0, &phb->mr_regs);
- }
-
- /* Map ESB if enabled */
- if (memory_region_is_mapped(&stack->intbar)) {
- memory_region_add_subregion(&stack->intbar, 0, &phb->xsrc.esb_mmio);
- }
-
- /* Check/update m32 */
- pnv_phb4_check_all_mbt(phb);
-}
-
void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon)
{
uint32_t offset = phb->regs[PHB_INT_NOTIFY_INDEX >> 3];
diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index f3e4fa0c82..7fe7f1f007 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -19,6 +19,7 @@
#include "hw/pci/pci_bus.h"
#include "hw/ppc/pnv.h"
#include "hw/qdev-properties.h"
+#include "sysemu/sysemu.h"
#include <libfdt.h>
@@ -111,258 +112,6 @@ static const MemoryRegionOps pnv_pec_pci_xscom_ops = {
.endianness = DEVICE_BIG_ENDIAN,
};
-static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
- uint32_t reg = addr >> 3;
-
- /* TODO: add list of allowed registers and error out if not */
- return stack->nest_regs[reg];
-}
-
-static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack)
-{
- PnvPhb4PecState *pec = stack->pec;
- MemoryRegion *sysmem = get_system_memory();
- uint64_t bar_en = stack->nest_regs[PEC_NEST_STK_BAR_EN];
- uint64_t bar, mask, size;
- char name[64];
-
- /*
- * NOTE: This will really not work well if those are remapped
- * after the PHB has created its sub regions. We could do better
- * if we had a way to resize regions but we don't really care
- * that much in practice as the stuff below really only happens
- * once early during boot
- */
-
- /* Handle unmaps */
- if (memory_region_is_mapped(&stack->mmbar0) &&
- !(bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) {
- memory_region_del_subregion(sysmem, &stack->mmbar0);
- }
- if (memory_region_is_mapped(&stack->mmbar1) &&
- !(bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) {
- memory_region_del_subregion(sysmem, &stack->mmbar1);
- }
- if (memory_region_is_mapped(&stack->phbbar) &&
- !(bar_en & PEC_NEST_STK_BAR_EN_PHB)) {
- memory_region_del_subregion(sysmem, &stack->phbbar);
- }
- if (memory_region_is_mapped(&stack->intbar) &&
- !(bar_en & PEC_NEST_STK_BAR_EN_INT)) {
- memory_region_del_subregion(sysmem, &stack->intbar);
- }
-
- /* Update PHB */
- pnv_phb4_update_regions(stack);
-
- /* Handle maps */
- if (!memory_region_is_mapped(&stack->mmbar0) &&
- (bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) {
- bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0] >> 8;
- mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0_MASK];
- size = ((~mask) >> 8) + 1;
- snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio0",
- pec->chip_id, pec->index, stack->stack_no);
- memory_region_init(&stack->mmbar0, OBJECT(stack), name, size);
- memory_region_add_subregion(sysmem, bar, &stack->mmbar0);
- stack->mmio0_base = bar;
- stack->mmio0_size = size;
- }
- if (!memory_region_is_mapped(&stack->mmbar1) &&
- (bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) {
- bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1] >> 8;
- mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1_MASK];
- size = ((~mask) >> 8) + 1;
- snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio1",
- pec->chip_id, pec->index, stack->stack_no);
- memory_region_init(&stack->mmbar1, OBJECT(stack), name, size);
- memory_region_add_subregion(sysmem, bar, &stack->mmbar1);
- stack->mmio1_base = bar;
- stack->mmio1_size = size;
- }
- if (!memory_region_is_mapped(&stack->phbbar) &&
- (bar_en & PEC_NEST_STK_BAR_EN_PHB)) {
- bar = stack->nest_regs[PEC_NEST_STK_PHB_REGS_BAR] >> 8;
- size = PNV_PHB4_NUM_REGS << 3;
- snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-phb",
- pec->chip_id, pec->index, stack->stack_no);
- memory_region_init(&stack->phbbar, OBJECT(stack), name, size);
- memory_region_add_subregion(sysmem, bar, &stack->phbbar);
- }
- if (!memory_region_is_mapped(&stack->intbar) &&
- (bar_en & PEC_NEST_STK_BAR_EN_INT)) {
- bar = stack->nest_regs[PEC_NEST_STK_INT_BAR] >> 8;
- size = PNV_PHB4_MAX_INTs << 16;
- snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-int",
- stack->pec->chip_id, stack->pec->index, stack->stack_no);
- memory_region_init(&stack->intbar, OBJECT(stack), name, size);
- memory_region_add_subregion(sysmem, bar, &stack->intbar);
- }
-
- /* Update PHB */
- pnv_phb4_update_regions(stack);
-}
-
-static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
-{
- PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
- PnvPhb4PecState *pec = stack->pec;
- uint32_t reg = addr >> 3;
-
- switch (reg) {
- case PEC_NEST_STK_PCI_NEST_FIR:
- stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] = val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_CLR:
- stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] &= val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_SET:
- stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] |= val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_MSK:
- stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] = val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_MSKC:
- stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] &= val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_MSKS:
- stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] |= val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_ACT0:
- case PEC_NEST_STK_PCI_NEST_FIR_ACT1:
- stack->nest_regs[reg] = val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_WOF:
- stack->nest_regs[reg] = 0;
- break;
- case PEC_NEST_STK_ERR_REPORT_0:
- case PEC_NEST_STK_ERR_REPORT_1:
- case PEC_NEST_STK_PBCQ_GNRL_STATUS:
- /* Flag error ? */
- break;
- case PEC_NEST_STK_PBCQ_MODE:
- stack->nest_regs[reg] = val & 0xff00000000000000ull;
- break;
- case PEC_NEST_STK_MMIO_BAR0:
- case PEC_NEST_STK_MMIO_BAR0_MASK:
- case PEC_NEST_STK_MMIO_BAR1:
- case PEC_NEST_STK_MMIO_BAR1_MASK:
- if (stack->nest_regs[PEC_NEST_STK_BAR_EN] &
- (PEC_NEST_STK_BAR_EN_MMIO0 |
- PEC_NEST_STK_BAR_EN_MMIO1)) {
- phb_pec_error(pec, "Changing enabled BAR unsupported\n");
- }
- stack->nest_regs[reg] = val & 0xffffffffff000000ull;
- break;
- case PEC_NEST_STK_PHB_REGS_BAR:
- if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_PHB) {
- phb_pec_error(pec, "Changing enabled BAR unsupported\n");
- }
- stack->nest_regs[reg] = val & 0xffffffffffc00000ull;
- break;
- case PEC_NEST_STK_INT_BAR:
- if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_INT) {
- phb_pec_error(pec, "Changing enabled BAR unsupported\n");
- }
- stack->nest_regs[reg] = val & 0xfffffff000000000ull;
- break;
- case PEC_NEST_STK_BAR_EN:
- stack->nest_regs[reg] = val & 0xf000000000000000ull;
- pnv_pec_stk_update_map(stack);
- break;
- case PEC_NEST_STK_DATA_FRZ_TYPE:
- case PEC_NEST_STK_PBCQ_TUN_BAR:
- /* Not used for now */
- stack->nest_regs[reg] = val;
- break;
- default:
- qemu_log_mask(LOG_UNIMP, "phb4_pec: nest_xscom_write 0x%"HWADDR_PRIx
- "=%"PRIx64"\n", addr, val);
- }
-}
-
-static const MemoryRegionOps pnv_pec_stk_nest_xscom_ops = {
- .read = pnv_pec_stk_nest_xscom_read,
- .write = pnv_pec_stk_nest_xscom_write,
- .valid.min_access_size = 8,
- .valid.max_access_size = 8,
- .impl.min_access_size = 8,
- .impl.max_access_size = 8,
- .endianness = DEVICE_BIG_ENDIAN,
-};
-
-static uint64_t pnv_pec_stk_pci_xscom_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
- uint32_t reg = addr >> 3;
-
- /* TODO: add list of allowed registers and error out if not */
- return stack->pci_regs[reg];
-}
-
-static void pnv_pec_stk_pci_xscom_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
-{
- PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
- uint32_t reg = addr >> 3;
-
- switch (reg) {
- case PEC_PCI_STK_PCI_FIR:
- stack->nest_regs[reg] = val;
- break;
- case PEC_PCI_STK_PCI_FIR_CLR:
- stack->nest_regs[PEC_PCI_STK_PCI_FIR] &= val;
- break;
- case PEC_PCI_STK_PCI_FIR_SET:
- stack->nest_regs[PEC_PCI_STK_PCI_FIR] |= val;
- break;
- case PEC_PCI_STK_PCI_FIR_MSK:
- stack->nest_regs[reg] = val;
- break;
- case PEC_PCI_STK_PCI_FIR_MSKC:
- stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] &= val;
- break;
- case PEC_PCI_STK_PCI_FIR_MSKS:
- stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] |= val;
- break;
- case PEC_PCI_STK_PCI_FIR_ACT0:
- case PEC_PCI_STK_PCI_FIR_ACT1:
- stack->nest_regs[reg] = val;
- break;
- case PEC_PCI_STK_PCI_FIR_WOF:
- stack->nest_regs[reg] = 0;
- break;
- case PEC_PCI_STK_ETU_RESET:
- stack->nest_regs[reg] = val & 0x8000000000000000ull;
- /* TODO: Implement reset */
- break;
- case PEC_PCI_STK_PBAIB_ERR_REPORT:
- break;
- case PEC_PCI_STK_PBAIB_TX_CMD_CRED:
- case PEC_PCI_STK_PBAIB_TX_DAT_CRED:
- stack->nest_regs[reg] = val;
- break;
- default:
- qemu_log_mask(LOG_UNIMP, "phb4_pec_stk: pci_xscom_write 0x%"HWADDR_PRIx
- "=%"PRIx64"\n", addr, val);
- }
-}
-
-static const MemoryRegionOps pnv_pec_stk_pci_xscom_ops = {
- .read = pnv_pec_stk_pci_xscom_read,
- .write = pnv_pec_stk_pci_xscom_write,
- .valid.min_access_size = 8,
- .valid.max_access_size = 8,
- .impl.min_access_size = 8,
- .impl.max_access_size = 8,
- .endianness = DEVICE_BIG_ENDIAN,
-};
-
static void pnv_pec_instance_init(Object *obj)
{
PnvPhb4PecState *pec = PNV_PHB4_PEC(obj);
@@ -374,19 +123,6 @@ static void pnv_pec_instance_init(Object *obj)
}
}
-static int pnv_pec_phb_offset(PnvPhb4PecState *pec)
-{
- PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
- int index = pec->index;
- int offset = 0;
-
- while (index--) {
- offset += pecc->num_stacks[index];
- }
-
- return offset;
-}
-
static void pnv_pec_realize(DeviceState *dev, Error **errp)
{
PnvPhb4PecState *pec = PNV_PHB4_PEC(dev);
@@ -405,10 +141,8 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp)
for (i = 0; i < pec->num_stacks; i++) {
PnvPhb4PecStack *stack = &pec->stacks[i];
Object *stk_obj = OBJECT(stack);
- int phb_id = pnv_pec_phb_offset(pec) + i;
object_property_set_int(stk_obj, "stack-no", i, &error_abort);
- object_property_set_int(stk_obj, "phb-id", phb_id, &error_abort);
object_property_set_link(stk_obj, "pec", OBJECT(pec), &error_abort);
if (!qdev_realize(DEVICE(stk_obj), NULL, errp)) {
return;
@@ -462,8 +196,7 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt,
pecc->compat_size)));
for (i = 0; i < pec->num_stacks; i++) {
- PnvPhb4PecStack *stack = &pec->stacks[i];
- PnvPHB4 *phb = &stack->phb;
+ int phb_id = pnv_phb4_pec_get_phb_id(pec, i);
int stk_offset;
name = g_strdup_printf("stack@%x", i);
@@ -473,7 +206,7 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt,
_FDT((fdt_setprop(fdt, stk_offset, "compatible", pecc->stk_compat,
pecc->stk_compat_size)));
_FDT((fdt_setprop_cell(fdt, stk_offset, "reg", i)));
- _FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", phb->phb_id)));
+ _FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", phb_id)));
}
return 0;
@@ -543,69 +276,38 @@ static const TypeInfo pnv_pec_type_info = {
}
};
-static void pnv_pec_stk_instance_init(Object *obj)
+static void pnv_pec_stk_default_phb_realize(PnvPhb4PecStack *stack,
+ Error **errp)
{
- PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(obj);
-
- object_initialize_child(obj, "phb", &stack->phb, TYPE_PNV_PHB4);
- object_property_add_alias(obj, "phb-id", OBJECT(&stack->phb), "index");
-}
-
-static void pnv_pec_stk_realize(DeviceState *dev, Error **errp)
-{
- PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev);
PnvPhb4PecState *pec = stack->pec;
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
- PnvChip *chip = pec->chip;
- uint32_t pec_nest_base;
- uint32_t pec_pci_base;
- char name[64];
-
- assert(pec);
-
- /* Initialize the XSCOM regions for the stack registers */
- snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest-stack-%d",
- pec->chip_id, pec->index, stack->stack_no);
- pnv_xscom_region_init(&stack->nest_regs_mr, OBJECT(stack),
- &pnv_pec_stk_nest_xscom_ops, stack, name,
- PHB4_PEC_NEST_STK_REGS_COUNT);
-
- snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d",
- pec->chip_id, pec->index, stack->stack_no);
- pnv_xscom_region_init(&stack->pci_regs_mr, OBJECT(stack),
- &pnv_pec_stk_pci_xscom_ops, stack, name,
- PHB4_PEC_PCI_STK_REGS_COUNT);
+ int phb_id = pnv_phb4_pec_get_phb_id(pec, stack->stack_no);
- /* PHB pass-through */
- snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d-phb",
- pec->chip_id, pec->index, stack->stack_no);
- pnv_xscom_region_init(&stack->phb_regs_mr, OBJECT(&stack->phb),
- &pnv_phb4_xscom_ops, &stack->phb, name, 0x40);
+ stack->phb = PNV_PHB4(qdev_new(TYPE_PNV_PHB4));
- object_property_set_int(OBJECT(&stack->phb), "chip-id", pec->chip_id,
+ object_property_set_int(OBJECT(stack->phb), "chip-id", pec->chip_id,
&error_fatal);
- object_property_set_int(OBJECT(&stack->phb), "version", pecc->version,
+ object_property_set_int(OBJECT(stack->phb), "index", phb_id,
&error_fatal);
- object_property_set_link(OBJECT(&stack->phb), "stack", OBJECT(stack),
+ object_property_set_int(OBJECT(stack->phb), "version", pecc->version,
+ &error_fatal);
+ object_property_set_link(OBJECT(stack->phb), "stack", OBJECT(stack),
&error_abort);
- if (!sysbus_realize(SYS_BUS_DEVICE(&stack->phb), errp)) {
+
+ if (!sysbus_realize(SYS_BUS_DEVICE(stack->phb), errp)) {
+ return;
+ }
+}
+
+static void pnv_pec_stk_realize(DeviceState *dev, Error **errp)
+{
+ PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev);
+
+ if (!defaults_enabled()) {
return;
}
- pec_nest_base = pecc->xscom_nest_base(pec);
- pec_pci_base = pecc->xscom_pci_base(pec);
-
- /* Populate the XSCOM address space. */
- pnv_xscom_add_subregion(chip,
- pec_nest_base + 0x40 * (stack->stack_no + 1),
- &stack->nest_regs_mr);
- pnv_xscom_add_subregion(chip,
- pec_pci_base + 0x40 * (stack->stack_no + 1),
- &stack->pci_regs_mr);
- pnv_xscom_add_subregion(chip,
- pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 +
- 0x40 * stack->stack_no,
- &stack->phb_regs_mr);
+ pnv_pec_stk_default_phb_realize(stack, errp);
}
static Property pnv_pec_stk_properties[] = {
@@ -630,7 +332,6 @@ static const TypeInfo pnv_pec_stk_type_info = {
.name = TYPE_PNV_PHB4_PEC_STACK,
.parent = TYPE_DEVICE,
.instance_size = sizeof(PnvPhb4PecStack),
- .instance_init = pnv_pec_stk_instance_init,
.class_init = pnv_pec_stk_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_PNV_XSCOM_INTERFACE },
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 9de8b83530..837146a2fb 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1099,7 +1099,6 @@ static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
static void pnv_chip_power8_instance_init(Object *obj)
{
- PnvChip *chip = PNV_CHIP(obj);
Pnv8Chip *chip8 = PNV8_CHIP(obj);
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
int i;
@@ -1117,14 +1116,14 @@ static void pnv_chip_power8_instance_init(Object *obj)
object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
- for (i = 0; i < pcc->num_phbs; i++) {
+ if (defaults_enabled()) {
+ chip8->num_phbs = pcc->num_phbs;
+ }
+
+ for (i = 0; i < chip8->num_phbs; i++) {
object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3);
}
- /*
- * Number of PHBs is the chip default
- */
- chip->num_phbs = pcc->num_phbs;
}
static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
@@ -1156,6 +1155,14 @@ static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
}
}
+/* Attach a root port device */
+void pnv_phb_attach_root_port(PCIHostState *pci, const char *name)
+{
+ PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name);
+
+ pci_realize_and_unref(root, pci->bus, &error_fatal);
+}
+
static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
{
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
@@ -1239,7 +1246,7 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
&chip8->homer.regs);
/* PHB3 controllers */
- for (i = 0; i < chip->num_phbs; i++) {
+ for (i = 0; i < chip8->num_phbs; i++) {
PnvPHB3 *phb = &chip8->phbs[i];
object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
@@ -1806,6 +1813,36 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
return NULL;
}
+void pnv_chip_parent_fixup(PnvChip *chip, Object *obj, int index)
+{
+ Object *parent = OBJECT(chip);
+ g_autofree char *default_id =
+ g_strdup_printf("%s[%d]", object_get_typename(obj), index);
+
+ if (obj->parent == parent) {
+ return;
+ }
+
+ object_ref(obj);
+ object_unparent(obj);
+ object_property_add_child(
+ parent, DEVICE(obj)->id ? DEVICE(obj)->id : default_id, obj);
+ object_unref(obj);
+}
+
+PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id)
+{
+ int i;
+
+ for (i = 0; i < pnv->num_chips; i++) {
+ PnvChip *chip = pnv->chips[i];
+ if (chip->chip_id == chip_id) {
+ return chip;
+ }
+ }
+ return NULL;
+}
+
static int pnv_ics_resend_child(Object *child, void *opaque)
{
PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
@@ -1903,6 +1940,8 @@ static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
pmc->compat = compat;
pmc->compat_size = sizeof(compat);
+
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB3);
}
static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
@@ -1921,6 +1960,8 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
pmc->compat = compat;
pmc->compat_size = sizeof(compat);
pmc->dt_power_mgt = pnv_dt_power_mgt;
+
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB4);
}
static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 8373429325..72f5dce751 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -723,10 +723,12 @@ static void spapr_dt_cpu(CPUState *cs, void *fdt, int offset,
*
* Only CPUs for which we create core types in spapr_cpu_core.c
* are possible, and all of those have VMX */
- if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) {
- _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2)));
- } else {
- _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1)));
+ if (env->insns_flags & PPC_ALTIVEC) {
+ if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) {
+ _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2)));
+ } else {
+ _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1)));
+ }
}
/* Advertise DFP (Decimal Floating Point) if available
diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
index 18eb824c97..29575cbaf6 100644
--- a/hw/scsi/virtio-scsi-dataplane.c
+++ b/hw/scsi/virtio-scsi-dataplane.c
@@ -49,51 +49,6 @@ void virtio_scsi_dataplane_setup(VirtIOSCSI *s, Error **errp)
}
}
-static bool virtio_scsi_data_plane_handle_cmd(VirtIODevice *vdev,
- VirtQueue *vq)
-{
- bool progress = false;
- VirtIOSCSI *s = VIRTIO_SCSI(vdev);
-
- virtio_scsi_acquire(s);
- if (!s->dataplane_fenced) {
- assert(s->ctx && s->dataplane_started);
- progress = virtio_scsi_handle_cmd_vq(s, vq);
- }
- virtio_scsi_release(s);
- return progress;
-}
-
-static bool virtio_scsi_data_plane_handle_ctrl(VirtIODevice *vdev,
- VirtQueue *vq)
-{
- bool progress = false;
- VirtIOSCSI *s = VIRTIO_SCSI(vdev);
-
- virtio_scsi_acquire(s);
- if (!s->dataplane_fenced) {
- assert(s->ctx && s->dataplane_started);
- progress = virtio_scsi_handle_ctrl_vq(s, vq);
- }
- virtio_scsi_release(s);
- return progress;
-}
-
-static bool virtio_scsi_data_plane_handle_event(VirtIODevice *vdev,
- VirtQueue *vq)
-{
- bool progress = false;
- VirtIOSCSI *s = VIRTIO_SCSI(vdev);
-
- virtio_scsi_acquire(s);
- if (!s->dataplane_fenced) {
- assert(s->ctx && s->dataplane_started);
- progress = virtio_scsi_handle_event_vq(s, vq);
- }
- virtio_scsi_release(s);
- return progress;
-}
-
static int virtio_scsi_set_host_notifier(VirtIOSCSI *s, VirtQueue *vq, int n)
{
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
@@ -118,10 +73,10 @@ static void virtio_scsi_dataplane_stop_bh(void *opaque)
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
int i;
- virtio_queue_aio_set_host_notifier_handler(vs->ctrl_vq, s->ctx, NULL);
- virtio_queue_aio_set_host_notifier_handler(vs->event_vq, s->ctx, NULL);
+ virtio_queue_aio_detach_host_notifier(vs->ctrl_vq, s->ctx);
+ virtio_queue_aio_detach_host_notifier(vs->event_vq, s->ctx);
for (i = 0; i < vs->conf.num_queues; i++) {
- virtio_queue_aio_set_host_notifier_handler(vs->cmd_vqs[i], s->ctx, NULL);
+ virtio_queue_aio_detach_host_notifier(vs->cmd_vqs[i], s->ctx);
}
}
@@ -182,14 +137,11 @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev)
memory_region_transaction_commit();
aio_context_acquire(s->ctx);
- virtio_queue_aio_set_host_notifier_handler(vs->ctrl_vq, s->ctx,
- virtio_scsi_data_plane_handle_ctrl);
- virtio_queue_aio_set_host_notifier_handler(vs->event_vq, s->ctx,
- virtio_scsi_data_plane_handle_event);
+ virtio_queue_aio_attach_host_notifier(vs->ctrl_vq, s->ctx);
+ virtio_queue_aio_attach_host_notifier(vs->event_vq, s->ctx);
for (i = 0; i < vs->conf.num_queues; i++) {
- virtio_queue_aio_set_host_notifier_handler(vs->cmd_vqs[i], s->ctx,
- virtio_scsi_data_plane_handle_cmd);
+ virtio_queue_aio_attach_host_notifier(vs->cmd_vqs[i], s->ctx);
}
s->dataplane_starting = false;
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 51fd09522a..34a968ecfb 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -720,7 +720,7 @@ static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
/* use non-QOM casts in the data path */
VirtIOSCSI *s = (VirtIOSCSI *)vdev;
- if (s->ctx) {
+ if (s->ctx && !s->dataplane_started) {
virtio_device_start_ioeventfd(vdev);
if (!s->dataplane_fenced) {
return;
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index bb5dbff68c..cd67a7bac8 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -116,8 +116,8 @@ struct SDState {
int32_t state; /* current card state, one of SDCardStates */
uint32_t vhs;
bool wp_switch;
- unsigned long *wp_groups;
- int32_t wpgrps_size;
+ unsigned long *wp_group_bmap;
+ int32_t wp_group_bits;
uint64_t size;
uint32_t blk_len;
uint32_t multi_blk_cnt;
@@ -290,12 +290,6 @@ FIELD(OCR, CARD_POWER_UP, 31, 1)
| R_OCR_CARD_CAPACITY_MASK \
| R_OCR_CARD_POWER_UP_MASK)
-static void sd_set_ocr(SDState *sd)
-{
- /* All voltages OK */
- sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK;
-}
-
static void sd_ocr_powerup(void *opaque)
{
SDState *sd = opaque;
@@ -311,6 +305,22 @@ static void sd_ocr_powerup(void *opaque)
}
}
+static void sd_set_ocr(SDState *sd)
+{
+ /* All voltages OK */
+ sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK;
+
+ if (sd->spi) {
+ /*
+ * We don't need to emulate power up sequence in SPI-mode.
+ * Thus, the card's power up status bit should be set to 1 when reset.
+ * The card's capacity status bit should also be set if SD card size
+ * is larger than 2GB for SDHC support.
+ */
+ sd_ocr_powerup(sd);
+ }
+}
+
static void sd_set_scr(SDState *sd)
{
sd->scr[0] = 0 << 4; /* SCR structure version 1.0 */
@@ -560,6 +570,7 @@ static void sd_reset(DeviceState *dev)
sd->state = sd_idle_state;
sd->rca = 0x0000;
+ sd->size = size;
sd_set_ocr(sd);
sd_set_scr(sd);
sd_set_cid(sd);
@@ -567,14 +578,13 @@ static void sd_reset(DeviceState *dev)
sd_set_cardstatus(sd);
sd_set_sdstatus(sd);
- g_free(sd->wp_groups);
+ g_free(sd->wp_group_bmap);
sd->wp_switch = sd->blk ? !blk_is_writable(sd->blk) : false;
- sd->wpgrps_size = sect;
- sd->wp_groups = bitmap_new(sd->wpgrps_size);
+ sd->wp_group_bits = sect;
+ sd->wp_group_bmap = bitmap_new(sd->wp_group_bits);
memset(sd->function_group, 0, sizeof(sd->function_group));
sd->erase_start = INVALID_ADDRESS;
sd->erase_end = INVALID_ADDRESS;
- sd->size = size;
sd->blk_len = 0x200;
sd->pwd_len = 0;
sd->expecting_acmd = false;
@@ -673,7 +683,7 @@ static const VMStateDescription sd_vmstate = {
VMSTATE_UINT32(card_status, SDState),
VMSTATE_PARTIAL_BUFFER(sd_status, SDState, 1),
VMSTATE_UINT32(vhs, SDState),
- VMSTATE_BITMAP(wp_groups, SDState, 0, wpgrps_size),
+ VMSTATE_BITMAP(wp_group_bmap, SDState, 0, wp_group_bits),
VMSTATE_UINT32(blk_len, SDState),
VMSTATE_UINT32(multi_blk_cnt, SDState),
VMSTATE_UINT32(erase_start, SDState),
@@ -803,8 +813,8 @@ static void sd_erase(SDState *sd)
if (sdsc) {
/* Only SDSC cards support write protect groups */
wpnum = sd_addr_to_wpnum(erase_addr);
- assert(wpnum < sd->wpgrps_size);
- if (test_bit(wpnum, sd->wp_groups)) {
+ assert(wpnum < sd->wp_group_bits);
+ if (test_bit(wpnum, sd->wp_group_bmap)) {
sd->card_status |= WP_ERASE_SKIP;
continue;
}
@@ -828,8 +838,8 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr)
*/
continue;
}
- assert(wpnum < sd->wpgrps_size);
- if (test_bit(wpnum, sd->wp_groups)) {
+ assert(wpnum < sd->wp_group_bits);
+ if (test_bit(wpnum, sd->wp_group_bmap)) {
ret |= (1 << i);
}
}
@@ -869,7 +879,7 @@ static void sd_function_switch(SDState *sd, uint32_t arg)
static inline bool sd_wp_addr(SDState *sd, uint64_t addr)
{
- return test_bit(sd_addr_to_wpnum(addr), sd->wp_groups);
+ return test_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap);
}
static void sd_lock_command(SDState *sd)
@@ -897,7 +907,7 @@ static void sd_lock_command(SDState *sd)
sd->card_status |= LOCK_UNLOCK_FAILED;
return;
}
- bitmap_zero(sd->wp_groups, sd->wpgrps_size);
+ bitmap_zero(sd->wp_group_bmap, sd->wp_group_bits);
sd->csd[14] &= ~0x10;
sd->card_status &= ~CARD_IS_LOCKED;
sd->pwd_len = 0;
@@ -1348,7 +1358,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
}
sd->state = sd_programming_state;
- set_bit(sd_addr_to_wpnum(addr), sd->wp_groups);
+ set_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap);
/* Bzzzzzzztt .... Operation complete. */
sd->state = sd_transfer_state;
return sd_r1b;
@@ -1370,7 +1380,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
}
sd->state = sd_programming_state;
- clear_bit(sd_addr_to_wpnum(addr), sd->wp_groups);
+ clear_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap);
/* Bzzzzzzztt .... Operation complete. */
sd->state = sd_transfer_state;
return sd_r1b;
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
index 8b6eaea407..7f6cc2f99b 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -632,7 +632,8 @@ int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p,
bool msos = (dev->flags & (1 << USB_DEV_FLAG_MSOS_DESC_IN_USE));
const USBDesc *desc = usb_device_get_usb_desc(dev);
const USBDescDevice *other_dev;
- uint8_t buf[256];
+ size_t buflen = USB_DESC_MAX_LEN;
+ g_autofree uint8_t *buf = g_malloc(buflen);
uint8_t type = value >> 8;
uint8_t index = value & 0xff;
int flags, ret = -1;
@@ -650,36 +651,36 @@ int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p,
switch(type) {
case USB_DT_DEVICE:
- ret = usb_desc_device(&desc->id, dev->device, msos, buf, sizeof(buf));
+ ret = usb_desc_device(&desc->id, dev->device, msos, buf, buflen);
trace_usb_desc_device(dev->addr, len, ret);
break;
case USB_DT_CONFIG:
if (index < dev->device->bNumConfigurations) {
ret = usb_desc_config(dev->device->confs + index, flags,
- buf, sizeof(buf));
+ buf, buflen);
}
trace_usb_desc_config(dev->addr, index, len, ret);
break;
case USB_DT_STRING:
- ret = usb_desc_string(dev, index, buf, sizeof(buf));
+ ret = usb_desc_string(dev, index, buf, buflen);
trace_usb_desc_string(dev->addr, index, len, ret);
break;
case USB_DT_DEVICE_QUALIFIER:
if (other_dev != NULL) {
- ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
+ ret = usb_desc_device_qualifier(other_dev, buf, buflen);
}
trace_usb_desc_device_qualifier(dev->addr, len, ret);
break;
case USB_DT_OTHER_SPEED_CONFIG:
if (other_dev != NULL && index < other_dev->bNumConfigurations) {
ret = usb_desc_config(other_dev->confs + index, flags,
- buf, sizeof(buf));
+ buf, buflen);
buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
}
trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
break;
case USB_DT_BOS:
- ret = usb_desc_bos(desc, buf, sizeof(buf));
+ ret = usb_desc_bos(desc, buf, buflen);
trace_usb_desc_bos(dev->addr, len, ret);
break;
diff --git a/hw/usb/desc.h b/hw/usb/desc.h
index 3ac604ecfa..35babdeff6 100644
--- a/hw/usb/desc.h
+++ b/hw/usb/desc.h
@@ -199,6 +199,7 @@ struct USBDesc {
const USBDescMSOS *msos;
};
+#define USB_DESC_MAX_LEN 8192
#define USB_DESC_FLAG_SUPER (1 << 1)
/* little helpers */
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 599d6b52a0..c9f295e7e4 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -908,6 +908,7 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
p->status = USB_RET_STALL;
break;
}
+ return;
err_stream:
error_report("%s: invalid stream %d", __func__, p->stream);
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index ed687bc9f1..8323650c6a 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -69,6 +69,65 @@ static const USBDescStrings desc_strings = {
[STR_SERIALNUMBER] = "1",
};
+static const uint8_t qemu_wacom_hid_report_descriptor[] = {
+ 0x05, 0x01, /* Usage Page (Desktop) */
+ 0x09, 0x02, /* Usage (Mouse) */
+ 0xa1, 0x01, /* Collection (Application) */
+ 0x85, 0x01, /* Report ID (1) */
+ 0x09, 0x01, /* Usage (Pointer) */
+ 0xa1, 0x00, /* Collection (Physical) */
+ 0x05, 0x09, /* Usage Page (Button) */
+ 0x19, 0x01, /* Usage Minimum (01h) */
+ 0x29, 0x03, /* Usage Maximum (03h) */
+ 0x15, 0x00, /* Logical Minimum (0) */
+ 0x25, 0x01, /* Logical Maximum (1) */
+ 0x95, 0x03, /* Report Count (3) */
+ 0x75, 0x01, /* Report Size (1) */
+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */
+ 0x95, 0x01, /* Report Count (1) */
+ 0x75, 0x05, /* Report Size (5) */
+ 0x81, 0x01, /* Input (Constant) */
+ 0x05, 0x01, /* Usage Page (Desktop) */
+ 0x09, 0x30, /* Usage (X) */
+ 0x09, 0x31, /* Usage (Y) */
+ 0x09, 0x38, /* Usage (Wheel) */
+ 0x15, 0x81, /* Logical Minimum (-127) */
+ 0x25, 0x7f, /* Logical Maximum (127) */
+ 0x75, 0x08, /* Report Size (8) */
+ 0x95, 0x03, /* Report Count (3) */
+ 0x81, 0x06, /* Input (Data, Variable, Relative) */
+ 0x95, 0x03, /* Report Count (3) */
+ 0x81, 0x01, /* Input (Constant) */
+ 0xc0, /* End Collection */
+ 0xc0, /* End Collection */
+ 0x05, 0x0d, /* Usage Page (Digitizer) */
+ 0x09, 0x01, /* Usage (Digitizer) */
+ 0xa1, 0x01, /* Collection (Application) */
+ 0x85, 0x02, /* Report ID (2) */
+ 0xa1, 0x00, /* Collection (Physical) */
+ 0x06, 0x00, 0xff,/* Usage Page (ff00h), vendor-defined */
+ 0x09, 0x01, /* Usage (01h) */
+ 0x15, 0x00, /* Logical Minimum (0) */
+ 0x26, 0xff, 0x00,/* Logical Maximum (255) */
+ 0x75, 0x08, /* Report Size (8) */
+ 0x95, 0x07, /* Report Count (7) */
+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */
+ 0xc0, /* End Collection */
+ 0x09, 0x01, /* Usage (01h) */
+ 0x85, 0x63, /* Report ID (99) */
+ 0x95, 0x07, /* Report Count (7) */
+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */
+ 0x09, 0x01, /* Usage (01h) */
+ 0x85, 0x02, /* Report ID (2) */
+ 0x95, 0x01, /* Report Count (1) */
+ 0xb1, 0x02, /* Feature (Variable) */
+ 0x09, 0x01, /* Usage (01h) */
+ 0x85, 0x03, /* Report ID (3) */
+ 0x95, 0x01, /* Report Count (1) */
+ 0xb1, 0x02, /* Feature (Variable) */
+ 0xc0 /* End Collection */
+};
+
static const USBDescIface desc_iface_wacom = {
.bInterfaceNumber = 0,
.bNumEndpoints = 1,
@@ -86,7 +145,7 @@ static const USBDescIface desc_iface_wacom = {
0x00, /* u8 country_code */
0x01, /* u8 num_descriptors */
USB_DT_REPORT, /* u8 type: Report */
- 0x6e, 0, /* u16 len */
+ sizeof(qemu_wacom_hid_report_descriptor), 0, /* u16 len */
},
},
},
@@ -266,6 +325,17 @@ static void usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
}
switch (request) {
+ case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
+ switch (value >> 8) {
+ case 0x22:
+ memcpy(data, qemu_wacom_hid_report_descriptor,
+ sizeof(qemu_wacom_hid_report_descriptor));
+ p->actual_length = sizeof(qemu_wacom_hid_report_descriptor);
+ break;
+ default:
+ return;
+ }
+ break;
case WACOM_SET_REPORT:
if (s->mouse_grabbed) {
qemu_remove_mouse_event_handler(s->eh_entry);
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 595ce015ff..f7ad6be5fb 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -53,7 +53,6 @@ vhost_vdpa_get_features(void *dev, uint64_t features) "dev: %p features: 0x%"PRI
vhost_vdpa_set_owner(void *dev) "dev: %p"
vhost_vdpa_vq_get_addr(void *dev, void *vq, uint64_t desc_user_addr, uint64_t avail_user_addr, uint64_t used_user_addr) "dev: %p vq: %p desc_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" used_user_addr: 0x%"PRIx64
vhost_vdpa_get_iova_range(void *dev, uint64_t first, uint64_t last) "dev: %p first: 0x%"PRIx64" last: 0x%"PRIx64
-vhost_vdpa_set_config_call(void *dev, int fd)"dev: %p fd: %d"
# virtio.c
virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned out_num) "elem %p size %zd in_num %u out_num %u"
diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
index 9b0349922e..c595957983 100644
--- a/hw/virtio/vhost-user-fs.c
+++ b/hw/virtio/vhost-user-fs.c
@@ -161,9 +161,6 @@ static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx,
{
VHostUserFS *fs = VHOST_USER_FS(vdev);
- if (idx == VIRTIO_CONFIG_IRQ_IDX) {
- return;
- }
vhost_virtqueue_mask(&fs->vhost_dev, vdev, idx, mask);
}
@@ -171,9 +168,6 @@ static bool vuf_guest_notifier_pending(VirtIODevice *vdev, int idx)
{
VHostUserFS *fs = VHOST_USER_FS(vdev);
- if (idx == VIRTIO_CONFIG_IRQ_IDX) {
- return false;
- }
return vhost_virtqueue_pending(&fs->vhost_dev, idx);
}
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index ac0cb575fb..04ea43704f 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -734,12 +734,6 @@ static int vhost_vdpa_set_vring_call(struct vhost_dev *dev,
trace_vhost_vdpa_set_vring_call(dev, file->index, file->fd);
return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file);
}
-static int vhost_vdpa_set_config_call(struct vhost_dev *dev,
- int fd)
-{
- trace_vhost_vdpa_set_config_call(dev, fd);
- return vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG_CALL, &fd);
-}
static int vhost_vdpa_get_features(struct vhost_dev *dev,
uint64_t *features)
@@ -810,5 +804,4 @@ const VhostOps vdpa_ops = {
.vhost_get_device_id = vhost_vdpa_get_device_id,
.vhost_vq_get_addr = vhost_vdpa_vq_get_addr,
.vhost_force_iommu = vhost_vdpa_force_iommu,
- .vhost_set_config_call = vhost_vdpa_set_config_call,
};
diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c
index d1b9c027b6..3f3771274e 100644
--- a/hw/virtio/vhost-vsock-common.c
+++ b/hw/virtio/vhost-vsock-common.c
@@ -125,9 +125,6 @@ static void vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx,
{
VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
- if (idx == VIRTIO_CONFIG_IRQ_IDX) {
- return;
- }
vhost_virtqueue_mask(&vvc->vhost_dev, vdev, idx, mask);
}
@@ -136,9 +133,6 @@ static bool vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev,
{
VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
- if (idx == VIRTIO_CONFIG_IRQ_IDX) {
- return false;
- }
return vhost_virtqueue_pending(&vvc->vhost_dev, idx);
}
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index cbf3b792da..7b03efccec 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1554,67 +1554,6 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
}
}
-bool vhost_config_pending(struct vhost_dev *hdev)
-{
- assert(hdev->vhost_ops);
- if ((hdev->started == false) ||
- (hdev->vhost_ops->vhost_set_config_call == NULL)) {
- return false;
- }
-
- EventNotifier *notifier =
- &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier;
- return event_notifier_test_and_clear(notifier);
-}
-
-void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask)
-{
- int fd;
- int r;
- EventNotifier *notifier =
- &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier;
- EventNotifier *config_notifier = &vdev->config_notifier;
- assert(hdev->vhost_ops);
-
- if ((hdev->started == false) ||
- (hdev->vhost_ops->vhost_set_config_call == NULL)) {
- return;
- }
- if (mask) {
- assert(vdev->use_guest_notifier_mask);
- fd = event_notifier_get_fd(notifier);
- } else {
- fd = event_notifier_get_fd(config_notifier);
- }
- r = hdev->vhost_ops->vhost_set_config_call(hdev, fd);
- if (r < 0) {
- VHOST_OPS_DEBUG(r, "vhost_set_config_call failed");
- }
-}
-
-static void vhost_stop_config_intr(struct vhost_dev *dev)
-{
- int fd = -1;
- assert(dev->vhost_ops);
- if (dev->vhost_ops->vhost_set_config_call) {
- dev->vhost_ops->vhost_set_config_call(dev, fd);
- }
-}
-
-static void vhost_start_config_intr(struct vhost_dev *dev)
-{
- int r;
-
- assert(dev->vhost_ops);
- int fd = event_notifier_get_fd(&dev->vdev->config_notifier);
- if (dev->vhost_ops->vhost_set_config_call) {
- r = dev->vhost_ops->vhost_set_config_call(dev, fd);
- if (!r) {
- event_notifier_set(&dev->vdev->config_notifier);
- }
- }
-}
-
uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
uint64_t features)
{
@@ -1827,16 +1766,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
}
}
- r = event_notifier_init(
- &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier, 0);
- if (r < 0) {
- return r;
- }
- event_notifier_test_and_clear(
- &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier);
- if (!vdev->use_guest_notifier_mask) {
- vhost_config_mask(hdev, vdev, true);
- }
if (hdev->log_enabled) {
uint64_t log_base;
@@ -1869,7 +1798,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
vhost_device_iotlb_miss(hdev, vq->used_phys, true);
}
}
- vhost_start_config_intr(hdev);
return 0;
fail_log:
vhost_log_put(hdev, false);
@@ -1895,9 +1823,6 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
/* should only be called after backend is connected */
assert(hdev->vhost_ops);
- event_notifier_test_and_clear(
- &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier);
- event_notifier_test_and_clear(&vdev->config_notifier);
if (hdev->vhost_ops->vhost_dev_start) {
hdev->vhost_ops->vhost_dev_start(hdev, false);
@@ -1915,7 +1840,6 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
}
memory_listener_unregister(&hdev->iommu_listener);
}
- vhost_stop_config_intr(hdev);
vhost_log_put(hdev, true);
hdev->started = false;
hdev->vdev = NULL;
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index 1d5192f8b4..54f9bbb789 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -948,9 +948,6 @@ static void virtio_crypto_guest_notifier_mask(VirtIODevice *vdev, int idx,
assert(vcrypto->vhost_started);
- if (idx == VIRTIO_CONFIG_IRQ_IDX) {
- return;
- }
cryptodev_vhost_virtqueue_mask(vdev, queue, idx, mask);
}
@@ -961,9 +958,6 @@ static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx)
assert(vcrypto->vhost_started);
- if (idx == VIRTIO_CONFIG_IRQ_IDX) {
- return false;
- }
return cryptodev_vhost_virtqueue_pending(vdev, queue, idx);
}
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 809132018b..72da12fea5 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -673,30 +673,7 @@ static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign,
return 0;
}
-static int virtio_mmio_set_config_guest_notifier(DeviceState *d, bool assign)
-{
- VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
- VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
- bool with_irqfd = false;
- EventNotifier *notifier = virtio_config_get_guest_notifier(vdev);
- int r = 0;
- if (assign) {
- r = event_notifier_init(notifier, 0);
- if (r < 0) {
- return r;
- }
- virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd);
- } else {
- virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd);
- event_notifier_cleanup(notifier);
- }
- if (vdc->guest_notifier_mask && vdev->use_guest_notifier_mask) {
- vdc->guest_notifier_mask(vdev, VIRTIO_CONFIG_IRQ_IDX, !assign);
- }
- return r;
-}
static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs,
bool assign)
{
@@ -718,10 +695,6 @@ static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs,
goto assign_error;
}
}
- r = virtio_mmio_set_config_guest_notifier(d, assign);
- if (r < 0) {
- goto assign_error;
- }
return 0;
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 98fb5493ae..750aa47ec1 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -677,6 +677,7 @@ static uint32_t virtio_read_config(PCIDevice *pci_dev,
}
static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
+ unsigned int queue_no,
unsigned int vector)
{
VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
@@ -703,160 +704,112 @@ static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy,
}
static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy,
- EventNotifier *n,
+ unsigned int queue_no,
unsigned int vector)
{
VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, queue_no);
+ EventNotifier *n = virtio_queue_get_guest_notifier(vq);
return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, irqfd->virq);
}
static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy,
- EventNotifier *n ,
+ unsigned int queue_no,
unsigned int vector)
{
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, queue_no);
+ EventNotifier *n = virtio_queue_get_guest_notifier(vq);
VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
int ret;
ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, irqfd->virq);
assert(ret == 0);
}
-static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no,
- EventNotifier **n, unsigned int *vector)
-{
- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
- VirtQueue *vq;
- if (queue_no == VIRTIO_CONFIG_IRQ_IDX) {
- *n = virtio_config_get_guest_notifier(vdev);
- *vector = vdev->config_vector;
- } else {
- if (!virtio_queue_get_num(vdev, queue_no)) {
- return -1;
- }
- *vector = virtio_queue_vector(vdev, queue_no);
- vq = virtio_get_queue(vdev, queue_no);
- *n = virtio_queue_get_guest_notifier(vq);
- }
- return 0;
-}
-
-static int kvm_virtio_pci_vector_use_one(VirtIOPCIProxy *proxy, int queue_no)
+static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
{
- unsigned int vector;
- int ret;
- EventNotifier *n;
PCIDevice *dev = &proxy->pci_dev;
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+ unsigned int vector;
+ int ret, queue_no;
- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector);
- if (ret < 0) {
- return ret;
- }
- if (vector >= msix_nr_vectors_allocated(dev)) {
- return 0;
- }
- ret = kvm_virtio_pci_vq_vector_use(proxy, vector);
- if (ret < 0) {
- goto undo;
- }
- /*
- * If guest supports masking, set up irqfd now.
- * Otherwise, delay until unmasked in the frontend.
- */
- if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
- ret = kvm_virtio_pci_irqfd_use(proxy, n, vector);
+ for (queue_no = 0; queue_no < nvqs; queue_no++) {
+ if (!virtio_queue_get_num(vdev, queue_no)) {
+ break;
+ }
+ vector = virtio_queue_vector(vdev, queue_no);
+ if (vector >= msix_nr_vectors_allocated(dev)) {
+ continue;
+ }
+ ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector);
if (ret < 0) {
- kvm_virtio_pci_vq_vector_release(proxy, vector);
goto undo;
}
+ /* If guest supports masking, set up irqfd now.
+ * Otherwise, delay until unmasked in the frontend.
+ */
+ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
+ ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector);
+ if (ret < 0) {
+ kvm_virtio_pci_vq_vector_release(proxy, vector);
+ goto undo;
+ }
+ }
}
-
return 0;
-undo:
- vector = virtio_queue_vector(vdev, queue_no);
- if (vector >= msix_nr_vectors_allocated(dev)) {
- return ret;
- }
- if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector);
- if (ret < 0) {
- return ret;
+undo:
+ while (--queue_no >= 0) {
+ vector = virtio_queue_vector(vdev, queue_no);
+ if (vector >= msix_nr_vectors_allocated(dev)) {
+ continue;
}
- kvm_virtio_pci_irqfd_release(proxy, n, vector);
- }
- return ret;
-}
-static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
-{
- int queue_no;
- int ret = 0;
- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
-
- for (queue_no = 0; queue_no < nvqs; queue_no++) {
- if (!virtio_queue_get_num(vdev, queue_no)) {
- return -1;
+ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
+ kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
}
- ret = kvm_virtio_pci_vector_use_one(proxy, queue_no);
+ kvm_virtio_pci_vq_vector_release(proxy, vector);
}
return ret;
}
-static int kvm_virtio_pci_vector_config_use(VirtIOPCIProxy *proxy)
-{
- return kvm_virtio_pci_vector_use_one(proxy, VIRTIO_CONFIG_IRQ_IDX);
-}
-
-static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy,
- int queue_no)
+static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
{
+ PCIDevice *dev = &proxy->pci_dev;
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
unsigned int vector;
- EventNotifier *n;
- int ret;
- VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
- PCIDevice *dev = &proxy->pci_dev;
-
- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector);
- if (ret < 0) {
- return;
- }
- if (vector >= msix_nr_vectors_allocated(dev)) {
- return;
- }
- if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
- kvm_virtio_pci_irqfd_release(proxy, n, vector);
- }
- kvm_virtio_pci_vq_vector_release(proxy, vector);
-}
-
-static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
-{
int queue_no;
- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
for (queue_no = 0; queue_no < nvqs; queue_no++) {
if (!virtio_queue_get_num(vdev, queue_no)) {
break;
}
- kvm_virtio_pci_vector_release_one(proxy, queue_no);
+ vector = virtio_queue_vector(vdev, queue_no);
+ if (vector >= msix_nr_vectors_allocated(dev)) {
+ continue;
+ }
+ /* If guest supports masking, clean up irqfd now.
+ * Otherwise, it was cleaned when masked in the frontend.
+ */
+ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
+ kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
+ }
+ kvm_virtio_pci_vq_vector_release(proxy, vector);
}
}
-static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy)
-{
- kvm_virtio_pci_vector_release_one(proxy, VIRTIO_CONFIG_IRQ_IDX);
-}
-
-static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy,
+static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
unsigned int queue_no,
unsigned int vector,
- MSIMessage msg,
- EventNotifier *n)
+ MSIMessage msg)
{
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+ VirtQueue *vq = virtio_get_queue(vdev, queue_no);
+ EventNotifier *n = virtio_queue_get_guest_notifier(vq);
VirtIOIRQFD *irqfd;
int ret = 0;
@@ -883,15 +836,14 @@ static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy,
event_notifier_set(n);
}
} else {
- ret = kvm_virtio_pci_irqfd_use(proxy, n, vector);
+ ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector);
}
return ret;
}
-static void virtio_pci_one_vector_mask(VirtIOPCIProxy *proxy,
+static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy,
unsigned int queue_no,
- unsigned int vector,
- EventNotifier *n)
+ unsigned int vector)
{
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
@@ -902,7 +854,7 @@ static void virtio_pci_one_vector_mask(VirtIOPCIProxy *proxy,
if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
k->guest_notifier_mask(vdev, queue_no, true);
} else {
- kvm_virtio_pci_irqfd_release(proxy, n, vector);
+ kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
}
}
@@ -912,7 +864,6 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtQueue *vq = virtio_vector_first_queue(vdev, vector);
- EventNotifier *n;
int ret, index, unmasked = 0;
while (vq) {
@@ -921,8 +872,7 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
break;
}
if (index < proxy->nvqs_with_notifiers) {
- n = virtio_queue_get_guest_notifier(vq);
- ret = virtio_pci_one_vector_unmask(proxy, index, vector, msg, n);
+ ret = virtio_pci_vq_vector_unmask(proxy, index, vector, msg);
if (ret < 0) {
goto undo;
}
@@ -930,24 +880,15 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
}
vq = virtio_vector_next_queue(vq);
}
- /* unmask config intr */
- n = virtio_config_get_guest_notifier(vdev);
- ret = virtio_pci_one_vector_unmask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector,
- msg, n);
- if (ret < 0) {
- goto undo_config;
- }
+
return 0;
-undo_config:
- n = virtio_config_get_guest_notifier(vdev);
- virtio_pci_one_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n);
+
undo:
vq = virtio_vector_first_queue(vdev, vector);
while (vq && unmasked >= 0) {
index = virtio_get_queue_index(vq);
if (index < proxy->nvqs_with_notifiers) {
- n = virtio_queue_get_guest_notifier(vq);
- virtio_pci_one_vector_mask(proxy, index, vector, n);
+ virtio_pci_vq_vector_mask(proxy, index, vector);
--unmasked;
}
vq = virtio_vector_next_queue(vq);
@@ -960,22 +901,18 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtQueue *vq = virtio_vector_first_queue(vdev, vector);
- EventNotifier *n;
int index;
while (vq) {
index = virtio_get_queue_index(vq);
- n = virtio_queue_get_guest_notifier(vq);
if (!virtio_queue_get_num(vdev, index)) {
break;
}
if (index < proxy->nvqs_with_notifiers) {
- virtio_pci_one_vector_mask(proxy, index, vector, n);
+ virtio_pci_vq_vector_mask(proxy, index, vector);
}
vq = virtio_vector_next_queue(vq);
}
- n = virtio_config_get_guest_notifier(vdev);
- virtio_pci_one_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n);
}
static void virtio_pci_vector_poll(PCIDevice *dev,
@@ -988,17 +925,19 @@ static void virtio_pci_vector_poll(PCIDevice *dev,
int queue_no;
unsigned int vector;
EventNotifier *notifier;
- int ret;
+ VirtQueue *vq;
for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
- ret = virtio_pci_get_notifier(proxy, queue_no, &notifier, &vector);
- if (ret < 0) {
+ if (!virtio_queue_get_num(vdev, queue_no)) {
break;
}
+ vector = virtio_queue_vector(vdev, queue_no);
if (vector < vector_start || vector >= vector_end ||
!msix_is_masked(dev, vector)) {
continue;
}
+ vq = virtio_get_queue(vdev, queue_no);
+ notifier = virtio_queue_get_guest_notifier(vq);
if (k->guest_notifier_pending) {
if (k->guest_notifier_pending(vdev, queue_no)) {
msix_set_pending(dev, vector);
@@ -1007,34 +946,6 @@ static void virtio_pci_vector_poll(PCIDevice *dev,
msix_set_pending(dev, vector);
}
}
- /* poll the config intr */
- ret = virtio_pci_get_notifier(proxy, VIRTIO_CONFIG_IRQ_IDX, &notifier,
- &vector);
- if (ret < 0) {
- return;
- }
- if (vector < vector_start || vector >= vector_end ||
- !msix_is_masked(dev, vector)) {
- return;
- }
- if (k->guest_notifier_pending) {
- if (k->guest_notifier_pending(vdev, VIRTIO_CONFIG_IRQ_IDX)) {
- msix_set_pending(dev, vector);
- }
- } else if (event_notifier_test_and_clear(notifier)) {
- msix_set_pending(dev, vector);
- }
-}
-
-void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq,
- int n, bool assign,
- bool with_irqfd)
-{
- if (n == VIRTIO_CONFIG_IRQ_IDX) {
- virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd);
- } else {
- virtio_queue_set_guest_notifier_fd_handler(vq, assign, with_irqfd);
- }
}
static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
@@ -1043,25 +954,17 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
- VirtQueue *vq = NULL;
- EventNotifier *notifier = NULL;
-
- if (n == VIRTIO_CONFIG_IRQ_IDX) {
- notifier = virtio_config_get_guest_notifier(vdev);
- } else {
- vq = virtio_get_queue(vdev, n);
- notifier = virtio_queue_get_guest_notifier(vq);
- }
+ VirtQueue *vq = virtio_get_queue(vdev, n);
+ EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
if (assign) {
int r = event_notifier_init(notifier, 0);
if (r < 0) {
return r;
}
- virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, true, with_irqfd);
+ virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
} else {
- virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, false,
- with_irqfd);
+ virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
event_notifier_cleanup(notifier);
}
@@ -1103,7 +1006,6 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
msix_unset_vector_notifiers(&proxy->pci_dev);
if (proxy->vector_irqfd) {
kvm_virtio_pci_vector_release(proxy, nvqs);
- kvm_virtio_pci_vector_config_release(proxy);
g_free(proxy->vector_irqfd);
proxy->vector_irqfd = NULL;
}
@@ -1119,11 +1021,7 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
goto assign_error;
}
}
- r = virtio_pci_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, assign,
- with_irqfd);
- if (r < 0) {
- goto config_assign_error;
- }
+
/* Must set vector notifier after guest notifier has been assigned */
if ((with_irqfd || k->guest_notifier_mask) && assign) {
if (with_irqfd) {
@@ -1132,14 +1030,11 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
msix_nr_vectors_allocated(&proxy->pci_dev));
r = kvm_virtio_pci_vector_use(proxy, nvqs);
if (r < 0) {
- goto config_assign_error;
+ goto assign_error;
}
}
- r = kvm_virtio_pci_vector_config_use(proxy);
- if (r < 0) {
- goto config_error;
- }
- r = msix_set_vector_notifiers(&proxy->pci_dev, virtio_pci_vector_unmask,
+ r = msix_set_vector_notifiers(&proxy->pci_dev,
+ virtio_pci_vector_unmask,
virtio_pci_vector_mask,
virtio_pci_vector_poll);
if (r < 0) {
@@ -1154,11 +1049,7 @@ notifiers_error:
assert(assign);
kvm_virtio_pci_vector_release(proxy, nvqs);
}
-config_error:
- kvm_virtio_pci_vector_config_release(proxy);
-config_assign_error:
- virtio_pci_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, !assign,
- with_irqfd);
+
assign_error:
/* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
assert(assign);
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index b704acc5a8..2446dcd9ae 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -251,7 +251,5 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t);
* @fixed_queues.
*/
unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues);
-void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq,
- int n, bool assign,
- bool with_irqfd);
+
#endif
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 971e59a663..aae72fb8b7 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -125,7 +125,6 @@ struct VirtQueue
uint16_t vector;
VirtIOHandleOutput handle_output;
- VirtIOHandleAIOOutput handle_aio_output;
VirtIODevice *vdev;
EventNotifier guest_notifier;
EventNotifier host_notifier;
@@ -2303,24 +2302,6 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align)
}
}
-static bool virtio_queue_notify_aio_vq(VirtQueue *vq)
-{
- bool ret = false;
-
- if (vq->vring.desc && vq->handle_aio_output) {
- VirtIODevice *vdev = vq->vdev;
-
- trace_virtio_queue_notify(vdev, vq - vdev->vq, vq);
- ret = vq->handle_aio_output(vdev, vq);
-
- if (unlikely(vdev->start_on_kick)) {
- virtio_set_started(vdev, true);
- }
- }
-
- return ret;
-}
-
static void virtio_queue_notify_vq(VirtQueue *vq)
{
if (vq->vring.desc && vq->handle_output) {
@@ -2399,7 +2380,6 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
vdev->vq[i].vring.num_default = queue_size;
vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN;
vdev->vq[i].handle_output = handle_output;
- vdev->vq[i].handle_aio_output = NULL;
vdev->vq[i].used_elems = g_malloc0(sizeof(VirtQueueElement) *
queue_size);
@@ -2411,7 +2391,6 @@ void virtio_delete_queue(VirtQueue *vq)
vq->vring.num = 0;
vq->vring.num_default = 0;
vq->handle_output = NULL;
- vq->handle_aio_output = NULL;
g_free(vq->used_elems);
vq->used_elems = NULL;
virtio_virtqueue_reset_region_cache(vq);
@@ -3494,14 +3473,7 @@ static void virtio_queue_guest_notifier_read(EventNotifier *n)
virtio_irq(vq);
}
}
-static void virtio_config_guest_notifier_read(EventNotifier *n)
-{
- VirtIODevice *vdev = container_of(n, VirtIODevice, config_notifier);
- if (event_notifier_test_and_clear(n)) {
- virtio_notify_config(vdev);
- }
-}
void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
bool with_irqfd)
{
@@ -3518,36 +3490,11 @@ void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
}
}
-void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev,
- bool assign, bool with_irqfd)
-{
- EventNotifier *n;
- n = &vdev->config_notifier;
- if (assign && !with_irqfd) {
- event_notifier_set_handler(n, virtio_config_guest_notifier_read);
- } else {
- event_notifier_set_handler(n, NULL);
- }
- if (!assign) {
- /* Test and clear notifier before closing it,*/
- /* in case poll callback didn't have time to run. */
- virtio_config_guest_notifier_read(n);
- }
-}
-
EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq)
{
return &vq->guest_notifier;
}
-static void virtio_queue_host_notifier_aio_read(EventNotifier *n)
-{
- VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
- if (event_notifier_test_and_clear(n)) {
- virtio_queue_notify_aio_vq(vq);
- }
-}
-
static void virtio_queue_host_notifier_aio_poll_begin(EventNotifier *n)
{
VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
@@ -3560,11 +3507,14 @@ static bool virtio_queue_host_notifier_aio_poll(void *opaque)
EventNotifier *n = opaque;
VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
- if (!vq->vring.desc || virtio_queue_empty(vq)) {
- return false;
- }
+ return vq->vring.desc && !virtio_queue_empty(vq);
+}
- return virtio_queue_notify_aio_vq(vq);
+static void virtio_queue_host_notifier_aio_poll_ready(EventNotifier *n)
+{
+ VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
+
+ virtio_queue_notify_vq(vq);
}
static void virtio_queue_host_notifier_aio_poll_end(EventNotifier *n)
@@ -3575,24 +3525,23 @@ static void virtio_queue_host_notifier_aio_poll_end(EventNotifier *n)
virtio_queue_set_notification(vq, 1);
}
-void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx,
- VirtIOHandleAIOOutput handle_output)
+void virtio_queue_aio_attach_host_notifier(VirtQueue *vq, AioContext *ctx)
{
- if (handle_output) {
- vq->handle_aio_output = handle_output;
- aio_set_event_notifier(ctx, &vq->host_notifier, true,
- virtio_queue_host_notifier_aio_read,
- virtio_queue_host_notifier_aio_poll);
- aio_set_event_notifier_poll(ctx, &vq->host_notifier,
- virtio_queue_host_notifier_aio_poll_begin,
- virtio_queue_host_notifier_aio_poll_end);
- } else {
- aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL, NULL);
- /* Test and clear notifier before after disabling event,
- * in case poll callback didn't have time to run. */
- virtio_queue_host_notifier_aio_read(&vq->host_notifier);
- vq->handle_aio_output = NULL;
- }
+ aio_set_event_notifier(ctx, &vq->host_notifier, true,
+ virtio_queue_host_notifier_read,
+ virtio_queue_host_notifier_aio_poll,
+ virtio_queue_host_notifier_aio_poll_ready);
+ aio_set_event_notifier_poll(ctx, &vq->host_notifier,
+ virtio_queue_host_notifier_aio_poll_begin,
+ virtio_queue_host_notifier_aio_poll_end);
+}
+
+void virtio_queue_aio_detach_host_notifier(VirtQueue *vq, AioContext *ctx)
+{
+ aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL, NULL, NULL);
+ /* Test and clear notifier before after disabling event,
+ * in case poll callback didn't have time to run. */
+ virtio_queue_host_notifier_read(&vq->host_notifier);
}
void virtio_queue_host_notifier_read(EventNotifier *n)
@@ -3608,11 +3557,6 @@ EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq)
return &vq->host_notifier;
}
-EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev)
-{
- return &vdev->config_notifier;
-}
-
void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled)
{
vq->host_notifier_enabled = enabled;
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index 416583f130..645a29a5a0 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -1115,11 +1115,11 @@ void xen_device_set_event_channel_context(XenDevice *xendev,
if (channel->ctx)
aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL);
channel->ctx = ctx;
aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
- xen_device_event, NULL, xen_device_poll, channel);
+ xen_device_event, NULL, xen_device_poll, NULL, channel);
}
XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
@@ -1193,7 +1193,7 @@ void xen_device_unbind_event_channel(XenDevice *xendev,
QLIST_REMOVE(channel, list);
aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL);
if (xenevtchn_unbind(channel->xeh, channel->local_port) < 0) {
error_setg_errno(errp, errno, "xenevtchn_unbind failed");
diff --git a/include/block/aio.h b/include/block/aio.h
index 47fbe9d81f..5634173b12 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -469,6 +469,7 @@ void aio_set_fd_handler(AioContext *ctx,
IOHandler *io_read,
IOHandler *io_write,
AioPollFn *io_poll,
+ IOHandler *io_poll_ready,
void *opaque);
/* Set polling begin/end callbacks for a file descriptor that has already been
@@ -490,7 +491,8 @@ void aio_set_event_notifier(AioContext *ctx,
EventNotifier *notifier,
bool is_external,
EventNotifierHandler *io_read,
- AioPollFn *io_poll);
+ AioPollFn *io_poll,
+ EventNotifierHandler *io_poll_ready);
/* Set polling begin/end callbacks for an event notifier that has already been
* registered with aio_set_event_notifier. Do nothing if the event notifier is
diff --git a/include/block/block.h b/include/block/block.h
index e5dd22b034..9d4050220b 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -269,12 +269,13 @@ enum {
BLK_PERM_RESIZE = 0x08,
/**
- * This permission is required to change the node that this BdrvChild
- * points to.
+ * There was a now-removed bit BLK_PERM_GRAPH_MOD, with value of 0x10. QEMU
+ * 6.1 and earlier may still lock the corresponding byte in block/file-posix
+ * locking. So, implementing some new permission should be very careful to
+ * not interfere with this old unused thing.
*/
- BLK_PERM_GRAPH_MOD = 0x10,
- BLK_PERM_ALL = 0x1f,
+ BLK_PERM_ALL = 0x0f,
DEFAULT_PERM_PASSTHROUGH = BLK_PERM_CONSISTENT_READ
| BLK_PERM_WRITE
diff --git a/include/block/block_int.h b/include/block/block_int.h
index f4c75e8ba9..27008cfb22 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -1122,9 +1122,6 @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
QDict *options);
-bool bdrv_backing_overridden(BlockDriverState *bs);
-
-
/**
* bdrv_add_aio_context_notifier:
*
diff --git a/include/hw/display/vga.h b/include/hw/display/vga.h
index 5f7825e0e3..a79aa2909b 100644
--- a/include/hw/display/vga.h
+++ b/include/hw/display/vga.h
@@ -9,8 +9,6 @@
#ifndef QEMU_HW_DISPLAY_VGA_H
#define QEMU_HW_DISPLAY_VGA_H
-#include "exec/hwaddr.h"
-
/*
* modules can reference this symbol to avoid being loaded
* into system emulators without vga support
@@ -24,8 +22,6 @@ enum vga_retrace_method {
extern enum vga_retrace_method vga_retrace_method;
-int isa_vga_mm_init(hwaddr vram_base,
- hwaddr ctrl_base, int it_shift,
- MemoryRegion *address_space);
+#define TYPE_VGA_MMIO "vga-mmio"
#endif
diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h
index e9c13e6bd8..af6ec83cf6 100644
--- a/include/hw/pci-host/pnv_phb3.h
+++ b/include/hw/pci-host/pnv_phb3.h
@@ -105,7 +105,7 @@ struct PnvPBCQState {
/*
* PHB3 PCIe Root port
*/
-#define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root-bus"
+#define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root"
#define TYPE_PNV_PHB3_ROOT_PORT "pnv-phb3-root-port"
@@ -155,8 +155,6 @@ struct PnvPHB3 {
PnvPBCQState pbcq;
- PnvPHB3RootPort root;
-
QLIST_HEAD(, PnvPhb3DMASpace) dma_spaces;
PnvChip *chip;
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 4a19338db3..4b7ce8a723 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -15,6 +15,7 @@
#include "hw/ppc/xive.h"
#include "qom/object.h"
+typedef struct PnvPhb4PecState PnvPhb4PecState;
typedef struct PnvPhb4PecStack PnvPhb4PecStack;
typedef struct PnvPHB4 PnvPHB4;
typedef struct PnvChip PnvChip;
@@ -46,7 +47,7 @@ typedef struct PnvPhb4DMASpace {
/*
* PHB4 PCIe Root port
*/
-#define TYPE_PNV_PHB4_ROOT_BUS "pnv-phb4-root-bus"
+#define TYPE_PNV_PHB4_ROOT_BUS "pnv-phb4-root"
#define TYPE_PNV_PHB4_ROOT_PORT "pnv-phb4-root-port"
typedef struct PnvPHB4RootPort {
@@ -78,8 +79,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4, PNV_PHB4)
struct PnvPHB4 {
PCIExpressHost parent_obj;
- PnvPHB4RootPort root;
-
uint32_t chip_id;
uint32_t phb_id;
@@ -132,7 +131,7 @@ struct PnvPHB4 {
};
void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon);
-void pnv_phb4_update_regions(PnvPhb4PecStack *stack);
+int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index);
extern const MemoryRegionOps pnv_phb4_xscom_ops;
/*
@@ -177,8 +176,11 @@ struct PnvPhb4PecStack {
/* The owner PEC */
PnvPhb4PecState *pec;
- /* The actual PHB */
- PnvPHB4 phb;
+ /*
+ * PHB4 pointer. pnv_phb4_update_regions() needs to access
+ * the PHB4 via a PnvPhb4PecStack pointer.
+ */
+ PnvPHB4 *phb;
};
struct PnvPhb4PecState {
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index c781525277..0e9e16544f 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -52,7 +52,6 @@ struct PnvChip {
uint64_t cores_mask;
PnvCore **cores;
- uint32_t num_phbs;
uint32_t num_pecs;
MemoryRegion xscom_mmio;
@@ -82,6 +81,7 @@ struct Pnv8Chip {
#define PNV8_CHIP_PHB3_MAX 4
PnvPHB3 phbs[PNV8_CHIP_PHB3_MAX];
+ uint32_t num_phbs;
XICSFabric *xics;
};
@@ -136,8 +136,8 @@ struct PnvChipClass {
/*< public >*/
uint64_t chip_cfam_id;
uint64_t cores_mask;
- uint32_t num_phbs;
uint32_t num_pecs;
+ uint32_t num_phbs;
DeviceRealize parent_realize;
@@ -177,6 +177,8 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10,
TYPE_PNV_CHIP_POWER10)
PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir);
+void pnv_phb_attach_root_port(PCIHostState *pci, const char *name);
+void pnv_chip_parent_fixup(PnvChip *chip, Object *obj, int index);
#define TYPE_PNV_MACHINE MACHINE_TYPE_NAME("powernv")
typedef struct PnvMachineClass PnvMachineClass;
@@ -217,6 +219,8 @@ struct PnvMachineState {
hwaddr fw_load_addr;
};
+PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id);
+
#define PNV_FDT_ADDR 0x01000000
#define PNV_TIMEBASE_FREQ 512000000ULL
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index ff34eb7c8a..81bf3109f8 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -126,8 +126,6 @@ typedef int (*vhost_get_device_id_op)(struct vhost_dev *dev, uint32_t *dev_id);
typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev);
-typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev,
- int fd);
typedef struct VhostOps {
VhostBackendType backend_type;
vhost_backend_init vhost_backend_init;
@@ -173,7 +171,6 @@ typedef struct VhostOps {
vhost_vq_get_addr_op vhost_vq_get_addr;
vhost_get_device_id_op vhost_get_device_id;
vhost_force_iommu_op vhost_force_iommu;
- vhost_set_config_call_op vhost_set_config_call;
} VhostOps;
int vhost_backend_update_device_iotlb(struct vhost_dev *dev,
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index b0f3b78987..58a73e7b7a 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -29,7 +29,6 @@ struct vhost_virtqueue {
unsigned long long used_phys;
unsigned used_size;
EventNotifier masked_notifier;
- EventNotifier masked_config_notifier;
struct vhost_dev *dev;
};
@@ -38,7 +37,6 @@ typedef unsigned long vhost_log_chunk_t;
#define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t))
#define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS)
#define VHOST_INVALID_FEATURE_BIT (0xff)
-#define VHOST_QUEUE_NUM_CONFIG_INR 0
struct vhost_log {
unsigned long long size;
@@ -118,8 +116,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);
int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev);
void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev);
-bool vhost_config_pending(struct vhost_dev *hdev);
-void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask);
/* Test and clear masked event pending status.
* Should be called after unmask to avoid losing events.
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index 29655a406d..d311c57cca 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -90,7 +90,7 @@ typedef struct MultiReqBuffer {
bool is_write;
} MultiReqBuffer;
-bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq);
+void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq);
void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh);
#endif
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index acfba7c76c..2179b75703 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -147,8 +147,8 @@ struct VirtIOGPUBaseClass {
DEFINE_PROP_UINT32("max_outputs", _state, _conf.max_outputs, 1), \
DEFINE_PROP_BIT("edid", _state, _conf.flags, \
VIRTIO_GPU_FLAG_EDID_ENABLED, true), \
- DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1024), \
- DEFINE_PROP_UINT32("yres", _state, _conf.yres, 768)
+ DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1280), \
+ DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800)
typedef struct VGPUDMABuf {
QemuDmaBuf buf;
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index d78088d872..f095637058 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -67,9 +67,6 @@ typedef struct VirtQueueElement
#define VIRTIO_NO_VECTOR 0xffff
-/* special index value used internally for config irqs */
-#define VIRTIO_CONFIG_IRQ_IDX -1
-
#define TYPE_VIRTIO_DEVICE "virtio-device"
OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE)
@@ -111,7 +108,6 @@ struct VirtIODevice
bool use_guest_notifier_mask;
AddressSpace *dma_as;
QLIST_HEAD(, VirtQueue) *vector_queues;
- EventNotifier config_notifier;
};
struct VirtioDeviceClass {
@@ -179,7 +175,6 @@ void virtio_error(VirtIODevice *vdev, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name);
typedef void (*VirtIOHandleOutput)(VirtIODevice *, VirtQueue *);
-typedef bool (*VirtIOHandleAIOOutput)(VirtIODevice *, VirtQueue *);
VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
VirtIOHandleOutput handle_output);
@@ -314,18 +309,15 @@ uint16_t virtio_get_queue_index(VirtQueue *vq);
EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq);
void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
bool with_irqfd);
-void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev,
- bool assign, bool with_irqfd);
int virtio_device_start_ioeventfd(VirtIODevice *vdev);
int virtio_device_grab_ioeventfd(VirtIODevice *vdev);
void virtio_device_release_ioeventfd(VirtIODevice *vdev);
bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev);
EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq);
-EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev);
void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled);
void virtio_queue_host_notifier_read(EventNotifier *n);
-void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx,
- VirtIOHandleAIOOutput handle_output);
+void virtio_queue_aio_attach_host_notifier(VirtQueue *vq, AioContext *ctx);
+void virtio_queue_aio_detach_host_notifier(VirtQueue *vq, AioContext *ctx);
VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector);
VirtQueue *virtio_vector_next_queue(VirtQueue *vq);
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index fc37498550..387e913e4e 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -39,8 +39,6 @@ int vhost_net_set_config(struct vhost_net *net, const uint8_t *data,
bool vhost_net_virtqueue_pending(VHostNetState *net, int n);
void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
int idx, bool mask);
-bool vhost_net_config_pending(VHostNetState *net);
-void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask);
int vhost_net_notify_migration_done(VHostNetState *net, char* mac_addr);
VHostNetState *get_vhost_net(NetClientState *nc);
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index a750f99b79..f9fb54d437 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -45,13 +45,10 @@ BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo);
void override_max_devs(BlockInterfaceType type, int max_devs);
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
-void drive_mark_claimed_by_board(void);
void drive_check_orphaned(void);
DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);
int drive_get_max_bus(BlockInterfaceType type);
-int drive_get_max_devs(BlockInterfaceType type);
-QemuOpts *drive_def(const char *optstr);
QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
const char *optstr);
DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type,
diff --git a/io/channel-command.c b/io/channel-command.c
index b2a9e27138..338da73ade 100644
--- a/io/channel-command.c
+++ b/io/channel-command.c
@@ -346,8 +346,10 @@ static void qio_channel_command_set_aio_fd_handler(QIOChannel *ioc,
void *opaque)
{
QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
- aio_set_fd_handler(ctx, cioc->readfd, false, io_read, NULL, NULL, opaque);
- aio_set_fd_handler(ctx, cioc->writefd, false, NULL, io_write, NULL, opaque);
+ aio_set_fd_handler(ctx, cioc->readfd, false,
+ io_read, NULL, NULL, NULL, opaque);
+ aio_set_fd_handler(ctx, cioc->writefd, false,
+ NULL, io_write, NULL, NULL, opaque);
}
diff --git a/io/channel-file.c b/io/channel-file.c
index c4bf799a80..d7cf6d278f 100644
--- a/io/channel-file.c
+++ b/io/channel-file.c
@@ -191,7 +191,8 @@ static void qio_channel_file_set_aio_fd_handler(QIOChannel *ioc,
void *opaque)
{
QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
- aio_set_fd_handler(ctx, fioc->fd, false, io_read, io_write, NULL, opaque);
+ aio_set_fd_handler(ctx, fioc->fd, false, io_read, io_write,
+ NULL, NULL, opaque);
}
static GSource *qio_channel_file_create_watch(QIOChannel *ioc,
diff --git a/io/channel-socket.c b/io/channel-socket.c
index 606ec97cf7..459922c874 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -761,7 +761,8 @@ static void qio_channel_socket_set_aio_fd_handler(QIOChannel *ioc,
void *opaque)
{
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
- aio_set_fd_handler(ctx, sioc->fd, false, io_read, io_write, NULL, opaque);
+ aio_set_fd_handler(ctx, sioc->fd, false,
+ io_read, io_write, NULL, NULL, opaque);
}
static GSource *qio_channel_socket_create_watch(QIOChannel *ioc,
diff --git a/linux-user/aarch64/target_structs.h b/linux-user/aarch64/target_structs.h
index 7c748344ca..3a06f373c3 100644
--- a/linux-user/aarch64/target_structs.h
+++ b/linux-user/aarch64/target_structs.h
@@ -1,58 +1 @@
-/*
- * ARM AArch64 specific structures for linux-user
- *
- * Copyright (c) 2013 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef AARCH64_TARGET_STRUCTS_H
-#define AARCH64_TARGET_STRUCTS_H
-
-struct target_ipc_perm {
- abi_int __key; /* Key. */
- abi_uint uid; /* Owner's user ID. */
- abi_uint gid; /* Owner's group ID. */
- abi_uint cuid; /* Creator's user ID. */
- abi_uint cgid; /* Creator's group ID. */
- abi_ushort mode; /* Read/write permission. */
- abi_ushort __pad1;
- abi_ushort __seq; /* Sequence number. */
- abi_ushort __pad2;
- abi_ulong __unused1;
- abi_ulong __unused2;
-};
-
-struct target_shmid_ds {
- struct target_ipc_perm shm_perm; /* operation permission struct */
- abi_long shm_segsz; /* size of segment in bytes */
- abi_ulong shm_atime; /* time of last shmat() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused1;
-#endif
- abi_ulong shm_dtime; /* time of last shmdt() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused2;
-#endif
- abi_ulong shm_ctime; /* time of last change by shmctl() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused3;
-#endif
- abi_int shm_cpid; /* pid of creator */
- abi_int shm_lpid; /* pid of last shmop */
- abi_ulong shm_nattch; /* number of current attaches */
- abi_ulong __unused4;
- abi_ulong __unused5;
-};
-
-#endif
+#include "../generic/target_structs.h"
diff --git a/linux-user/alpha/cpu_loop.c b/linux-user/alpha/cpu_loop.c
index 37c33f0ccd..de6e0c901c 100644
--- a/linux-user/alpha/cpu_loop.c
+++ b/linux-user/alpha/cpu_loop.c
@@ -27,8 +27,7 @@
void cpu_loop(CPUAlphaState *env)
{
CPUState *cs = env_cpu(env);
- int trapnr;
- target_siginfo_t info;
+ int trapnr, si_code;
abi_long sysret;
while (1) {
@@ -56,18 +55,10 @@ void cpu_loop(CPUAlphaState *env)
break;
case EXCP_OPCDEC:
do_sigill:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLOPC;
- info._sifields._sigfault._addr = env->pc;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
break;
case EXCP_ARITH:
- info.si_signo = TARGET_SIGFPE;
- info.si_errno = 0;
- info.si_code = TARGET_FPE_FLTINV;
- info._sifields._sigfault._addr = env->pc;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGFPE, TARGET_FPE_FLTINV, env->pc);
break;
case EXCP_FEN:
/* No-op. Linux simply re-enables the FPU. */
@@ -76,20 +67,10 @@ void cpu_loop(CPUAlphaState *env)
switch (env->error_code) {
case 0x80:
/* BPT */
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- info._sifields._sigfault._addr = env->pc;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
+ goto do_sigtrap_brkpt;
case 0x81:
/* BUGCHK */
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = 0;
- info._sifields._sigfault._addr = env->pc;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
+ goto do_sigtrap_unk;
case 0x83:
/* CALLSYS */
trapnr = env->ir[IR_V0];
@@ -130,47 +111,43 @@ void cpu_loop(CPUAlphaState *env)
abort();
case 0xAA:
/* GENTRAP */
- info.si_signo = TARGET_SIGFPE;
switch (env->ir[IR_A0]) {
case TARGET_GEN_INTOVF:
- info.si_code = TARGET_FPE_INTOVF;
+ si_code = TARGET_FPE_INTOVF;
break;
case TARGET_GEN_INTDIV:
- info.si_code = TARGET_FPE_INTDIV;
+ si_code = TARGET_FPE_INTDIV;
break;
case TARGET_GEN_FLTOVF:
- info.si_code = TARGET_FPE_FLTOVF;
+ si_code = TARGET_FPE_FLTOVF;
break;
case TARGET_GEN_FLTUND:
- info.si_code = TARGET_FPE_FLTUND;
+ si_code = TARGET_FPE_FLTUND;
break;
case TARGET_GEN_FLTINV:
- info.si_code = TARGET_FPE_FLTINV;
+ si_code = TARGET_FPE_FLTINV;
break;
case TARGET_GEN_FLTINE:
- info.si_code = TARGET_FPE_FLTRES;
+ si_code = TARGET_FPE_FLTRES;
break;
case TARGET_GEN_ROPRAND:
- info.si_code = 0;
+ si_code = TARGET_FPE_FLTUNK;
break;
default:
- info.si_signo = TARGET_SIGTRAP;
- info.si_code = 0;
- break;
+ goto do_sigtrap_unk;
}
- info.si_errno = 0;
- info._sifields._sigfault._addr = env->pc;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGFPE, si_code, env->pc);
break;
default:
goto do_sigill;
}
break;
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ do_sigtrap_brkpt:
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
+ break;
+ do_sigtrap_unk:
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_UNK, env->pc);
break;
case EXCP_INTERRUPT:
/* Just indicate that signals should be handled asap. */
diff --git a/linux-user/arm/target_structs.h b/linux-user/arm/target_structs.h
index 339b070bf1..3a06f373c3 100644
--- a/linux-user/arm/target_structs.h
+++ b/linux-user/arm/target_structs.h
@@ -1,59 +1 @@
-/*
- * ARM specific structures for linux-user
- *
- * Copyright (c) 2013 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef ARM_TARGET_STRUCTS_H
-#define ARM_TARGET_STRUCTS_H
-
-struct target_ipc_perm {
- abi_int __key; /* Key. */
- abi_uint uid; /* Owner's user ID. */
- abi_uint gid; /* Owner's group ID. */
- abi_uint cuid; /* Creator's user ID. */
- abi_uint cgid; /* Creator's group ID. */
- abi_ushort mode; /* Read/write permission. */
- abi_ushort __pad1;
- abi_ushort __seq; /* Sequence number. */
- abi_ushort __pad2;
- abi_ulong __unused1;
- abi_ulong __unused2;
-};
-
-struct target_shmid_ds {
- struct target_ipc_perm shm_perm; /* operation permission struct */
- abi_long shm_segsz; /* size of segment in bytes */
- abi_ulong shm_atime; /* time of last shmat() */
- abi_ulong __unused1;
- abi_ulong shm_dtime; /* time of last shmdt() */
- abi_ulong __unused2;
- abi_ulong shm_ctime; /* time of last change by shmctl() */
- abi_ulong __unused3;
- abi_int shm_cpid; /* pid of creator */
- abi_int shm_lpid; /* pid of last shmop */
- abi_ulong shm_nattch; /* number of current attaches */
- abi_ulong __unused4;
- abi_ulong __unused5;
-};
-
-struct target_oabi_flock64 {
- abi_short l_type;
- abi_short l_whence;
- abi_llong l_start;
- abi_llong l_len;
- abi_int l_pid;
-} QEMU_PACKED;
-#endif
+#include "../generic/target_structs.h"
diff --git a/linux-user/cris/cpu_loop.c b/linux-user/cris/cpu_loop.c
index 5213aebf55..0f46b3c1a8 100644
--- a/linux-user/cris/cpu_loop.c
+++ b/linux-user/cris/cpu_loop.c
@@ -28,8 +28,7 @@ void cpu_loop(CPUCRISState *env)
{
CPUState *cs = env_cpu(env);
int trapnr, ret;
- target_siginfo_t info;
-
+
while (1) {
cpu_exec_start(cs);
trapnr = cpu_exec(cs);
@@ -38,8 +37,8 @@ void cpu_loop(CPUCRISState *env)
switch (trapnr) {
case EXCP_INTERRUPT:
- /* just indicate that signals should be handled asap */
- break;
+ /* just indicate that signals should be handled asap */
+ break;
case EXCP_BREAK:
ret = do_syscall(env,
env->regs[9],
@@ -57,10 +56,7 @@ void cpu_loop(CPUCRISState *env)
}
break;
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
diff --git a/linux-user/cris/target_structs.h b/linux-user/cris/target_structs.h
index f949d2331e..3a06f373c3 100644
--- a/linux-user/cris/target_structs.h
+++ b/linux-user/cris/target_structs.h
@@ -1,58 +1 @@
-/*
- * CRIS specific structures for linux-user
- *
- * Copyright (c) 2013 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef CRIS_TARGET_STRUCTS_H
-#define CRIS_TARGET_STRUCTS_H
-
-struct target_ipc_perm {
- abi_int __key; /* Key. */
- abi_uint uid; /* Owner's user ID. */
- abi_uint gid; /* Owner's group ID. */
- abi_uint cuid; /* Creator's user ID. */
- abi_uint cgid; /* Creator's group ID. */
- abi_ushort mode; /* Read/write permission. */
- abi_ushort __pad1;
- abi_ushort __seq; /* Sequence number. */
- abi_ushort __pad2;
- abi_ulong __unused1;
- abi_ulong __unused2;
-};
-
-struct target_shmid_ds {
- struct target_ipc_perm shm_perm; /* operation permission struct */
- abi_long shm_segsz; /* size of segment in bytes */
- abi_ulong shm_atime; /* time of last shmat() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused1;
-#endif
- abi_ulong shm_dtime; /* time of last shmdt() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused2;
-#endif
- abi_ulong shm_ctime; /* time of last change by shmctl() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused3;
-#endif
- abi_int shm_cpid; /* pid of creator */
- abi_int shm_lpid; /* pid of last shmop */
- abi_ulong shm_nattch; /* number of current attaches */
- abi_ulong __unused4;
- abi_ulong __unused5;
-};
-
-#endif
+#include "../generic/target_structs.h"
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 329b2375ef..d3274edfdb 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2420,7 +2420,7 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
} else {
offset = -(HI_COMMPAGE & -align);
}
- } else if (LO_COMMPAGE) {
+ } else if (LO_COMMPAGE != 0) {
loaddr = MIN(loaddr, LO_COMMPAGE & -align);
}
diff --git a/linux-user/generic/target_structs.h b/linux-user/generic/target_structs.h
new file mode 100644
index 0000000000..09ff858b6e
--- /dev/null
+++ b/linux-user/generic/target_structs.h
@@ -0,0 +1,58 @@
+/*
+ * Generic structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GENERIC_TARGET_STRUCTS_H
+#define GENERIC_TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+ abi_int __key; /* Key. */
+ abi_uint uid; /* Owner's user ID. */
+ abi_uint gid; /* Owner's group ID. */
+ abi_uint cuid; /* Creator's user ID. */
+ abi_uint cgid; /* Creator's group ID. */
+ abi_ushort mode; /* Read/write permission. */
+ abi_ushort __pad1;
+ abi_ushort __seq; /* Sequence number. */
+ abi_ushort __pad2;
+ abi_ulong __unused1;
+ abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+ struct target_ipc_perm shm_perm; /* operation permission struct */
+ abi_long shm_segsz; /* size of segment in bytes */
+ abi_ulong shm_atime; /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+ abi_ulong __unused1;
+#endif
+ abi_ulong shm_dtime; /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+ abi_ulong __unused2;
+#endif
+ abi_ulong shm_ctime; /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+ abi_ulong __unused3;
+#endif
+ abi_int shm_cpid; /* pid of creator */
+ abi_int shm_lpid; /* pid of last shmop */
+ abi_ulong shm_nattch; /* number of current attaches */
+ abi_ulong __unused4;
+ abi_ulong __unused5;
+};
+
+#endif
diff --git a/linux-user/hexagon/target_structs.h b/linux-user/hexagon/target_structs.h
index c217d9442a..3a06f373c3 100644
--- a/linux-user/hexagon/target_structs.h
+++ b/linux-user/hexagon/target_structs.h
@@ -1,54 +1 @@
-/*
- * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Hexagon specific structures for linux-user
- */
-#ifndef HEXAGON_TARGET_STRUCTS_H
-#define HEXAGON_TARGET_STRUCTS_H
-
-struct target_ipc_perm {
- abi_int __key; /* Key. */
- abi_uint uid; /* Owner's user ID. */
- abi_uint gid; /* Owner's group ID. */
- abi_uint cuid; /* Creator's user ID. */
- abi_uint cgid; /* Creator's group ID. */
- abi_ushort mode; /* Read/write permission. */
- abi_ushort __pad1;
- abi_ushort __seq; /* Sequence number. */
- abi_ushort __pad2;
- abi_ulong __unused1;
- abi_ulong __unused2;
-};
-
-struct target_shmid_ds {
- struct target_ipc_perm shm_perm; /* operation permission struct */
- abi_long shm_segsz; /* size of segment in bytes */
- abi_ulong shm_atime; /* time of last shmat() */
- abi_ulong __unused1;
- abi_ulong shm_dtime; /* time of last shmdt() */
- abi_ulong __unused2;
- abi_ulong shm_ctime; /* time of last change by shmctl() */
- abi_ulong __unused3;
- abi_int shm_cpid; /* pid of creator */
- abi_int shm_lpid; /* pid of last shmop */
- abi_ulong shm_nattch; /* number of current attaches */
- abi_ulong __unused4;
- abi_ulong __unused5;
-};
-
-#endif
+#include "../generic/target_structs.h"
diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c
index a47a63176b..a576d1a249 100644
--- a/linux-user/hppa/cpu_loop.c
+++ b/linux-user/hppa/cpu_loop.c
@@ -110,7 +110,6 @@ static abi_ulong hppa_lws(CPUHPPAState *env)
void cpu_loop(CPUHPPAState *env)
{
CPUState *cs = env_cpu(env);
- target_siginfo_t info;
abi_ulong ret;
int trapnr;
@@ -145,28 +144,25 @@ void cpu_loop(CPUHPPAState *env)
env->iaoq_b = env->gr[31] + 4;
break;
case EXCP_ILL:
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->iaoq_f);
+ break;
case EXCP_PRIV_OPR:
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f);
+ break;
case EXCP_PRIV_REG:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLOPN;
- info._sifields._sigfault._addr = env->iaoq_f;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVREG, env->iaoq_f);
break;
case EXCP_OVERFLOW:
+ force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->iaoq_f);
+ break;
case EXCP_COND:
+ force_sig_fault(TARGET_SIGFPE, TARGET_FPE_CONDTRAP, env->iaoq_f);
+ break;
case EXCP_ASSIST:
- info.si_signo = TARGET_SIGFPE;
- info.si_errno = 0;
- info.si_code = 0;
- info._sifields._sigfault._addr = env->iaoq_f;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f);
break;
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c
index 9aaae93e2f..29dfd7cd0c 100644
--- a/linux-user/i386/cpu_loop.c
+++ b/linux-user/i386/cpu_loop.c
@@ -84,17 +84,6 @@ static void set_idt(int n, unsigned int dpl)
}
#endif
-static void gen_signal(CPUX86State *env, int sig, int code, abi_ptr addr)
-{
- target_siginfo_t info = {
- .si_signo = sig,
- .si_code = code,
- ._sifields._sigfault._addr = addr
- };
-
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
-}
-
#ifdef TARGET_X86_64
static bool write_ok_or_segv(CPUX86State *env, abi_ptr addr, size_t len)
{
@@ -107,7 +96,7 @@ static bool write_ok_or_segv(CPUX86State *env, abi_ptr addr, size_t len)
}
env->error_code = PG_ERROR_W_MASK | PG_ERROR_U_MASK;
- gen_signal(env, TARGET_SIGSEGV, TARGET_SEGV_MAPERR, addr);
+ force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, addr);
return false;
}
@@ -193,11 +182,21 @@ static void emulate_vsyscall(CPUX86State *env)
return;
sigsegv:
- /* Like force_sig(SIGSEGV). */
- gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
+ force_sig(TARGET_SIGSEGV);
}
#endif
+static bool maybe_handle_vm86_trap(CPUX86State *env, int trapnr)
+{
+#ifndef TARGET_X86_64
+ if (env->eflags & VM_MASK) {
+ handle_vm86_trap(env, trapnr);
+ return true;
+ }
+#endif
+ return false;
+}
+
void cpu_loop(CPUX86State *env)
{
CPUState *cs = env_cpu(env);
@@ -255,65 +254,54 @@ void cpu_loop(CPUX86State *env)
#endif
case EXCP0B_NOSEG:
case EXCP0C_STACK:
- gen_signal(env, TARGET_SIGBUS, TARGET_SI_KERNEL, 0);
+ force_sig(TARGET_SIGBUS);
break;
case EXCP0D_GPF:
/* XXX: potential problem if ABI32 */
-#ifndef TARGET_X86_64
- if (env->eflags & VM_MASK) {
- handle_vm86_fault(env);
+ if (maybe_handle_vm86_trap(env, trapnr)) {
break;
}
-#endif
- gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
+ force_sig(TARGET_SIGSEGV);
break;
case EXCP0E_PAGE:
- gen_signal(env, TARGET_SIGSEGV,
- (env->error_code & 1 ?
- TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR),
- env->cr[2]);
+ force_sig_fault(TARGET_SIGSEGV,
+ (env->error_code & PG_ERROR_P_MASK ?
+ TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR),
+ env->cr[2]);
break;
case EXCP00_DIVZ:
-#ifndef TARGET_X86_64
- if (env->eflags & VM_MASK) {
- handle_vm86_trap(env, trapnr);
+ if (maybe_handle_vm86_trap(env, trapnr)) {
break;
}
-#endif
- gen_signal(env, TARGET_SIGFPE, TARGET_FPE_INTDIV, env->eip);
+ force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->eip);
break;
case EXCP01_DB:
- case EXCP03_INT3:
-#ifndef TARGET_X86_64
- if (env->eflags & VM_MASK) {
- handle_vm86_trap(env, trapnr);
+ if (maybe_handle_vm86_trap(env, trapnr)) {
break;
}
-#endif
- if (trapnr == EXCP01_DB) {
- gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip);
- } else {
- gen_signal(env, TARGET_SIGTRAP, TARGET_SI_KERNEL, 0);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip);
+ break;
+ case EXCP03_INT3:
+ if (maybe_handle_vm86_trap(env, trapnr)) {
+ break;
}
+ force_sig(TARGET_SIGTRAP);
break;
case EXCP04_INTO:
case EXCP05_BOUND:
-#ifndef TARGET_X86_64
- if (env->eflags & VM_MASK) {
- handle_vm86_trap(env, trapnr);
+ if (maybe_handle_vm86_trap(env, trapnr)) {
break;
}
-#endif
- gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
+ force_sig(TARGET_SIGSEGV);
break;
case EXCP06_ILLOP:
- gen_signal(env, TARGET_SIGILL, TARGET_ILL_ILLOPN, env->eip);
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->eip);
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
case EXCP_DEBUG:
- gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, 0);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip);
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
diff --git a/linux-user/i386/target_structs.h b/linux-user/i386/target_structs.h
index e22847fd20..3a06f373c3 100644
--- a/linux-user/i386/target_structs.h
+++ b/linux-user/i386/target_structs.h
@@ -1,58 +1 @@
-/*
- * i386 specific structures for linux-user
- *
- * Copyright (c) 2013 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef I386_TARGET_STRUCTS_H
-#define I386_TARGET_STRUCTS_H
-
-struct target_ipc_perm {
- abi_int __key; /* Key. */
- abi_uint uid; /* Owner's user ID. */
- abi_uint gid; /* Owner's group ID. */
- abi_uint cuid; /* Creator's user ID. */
- abi_uint cgid; /* Creator's group ID. */
- abi_ushort mode; /* Read/write permission. */
- abi_ushort __pad1;
- abi_ushort __seq; /* Sequence number. */
- abi_ushort __pad2;
- abi_ulong __unused1;
- abi_ulong __unused2;
-};
-
-struct target_shmid_ds {
- struct target_ipc_perm shm_perm; /* operation permission struct */
- abi_long shm_segsz; /* size of segment in bytes */
- abi_ulong shm_atime; /* time of last shmat() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused1;
-#endif
- abi_ulong shm_dtime; /* time of last shmdt() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused2;
-#endif
- abi_ulong shm_ctime; /* time of last change by shmctl() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused3;
-#endif
- abi_int shm_cpid; /* pid of creator */
- abi_int shm_lpid; /* pid of last shmop */
- abi_ulong shm_nattch; /* number of current attaches */
- abi_ulong __unused4;
- abi_ulong __unused5;
-};
-
-#endif
+#include "../generic/target_structs.h"
diff --git a/linux-user/host/aarch64/host-signal.h b/linux-user/include/host/aarch64/host-signal.h
index 9770b36dc1..9770b36dc1 100644
--- a/linux-user/host/aarch64/host-signal.h
+++ b/linux-user/include/host/aarch64/host-signal.h
diff --git a/linux-user/host/alpha/host-signal.h b/linux-user/include/host/alpha/host-signal.h
index f4c942948a..f4c942948a 100644
--- a/linux-user/host/alpha/host-signal.h
+++ b/linux-user/include/host/alpha/host-signal.h
diff --git a/linux-user/host/arm/host-signal.h b/linux-user/include/host/arm/host-signal.h
index 6c095773c0..6c095773c0 100644
--- a/linux-user/host/arm/host-signal.h
+++ b/linux-user/include/host/arm/host-signal.h
diff --git a/linux-user/host/i386/host-signal.h b/linux-user/include/host/i386/host-signal.h
index abe1ece5c9..abe1ece5c9 100644
--- a/linux-user/host/i386/host-signal.h
+++ b/linux-user/include/host/i386/host-signal.h
diff --git a/linux-user/host/loongarch64/host-signal.h b/linux-user/include/host/loongarch64/host-signal.h
index 7effa24251..7effa24251 100644
--- a/linux-user/host/loongarch64/host-signal.h
+++ b/linux-user/include/host/loongarch64/host-signal.h
diff --git a/linux-user/host/mips/host-signal.h b/linux-user/include/host/mips/host-signal.h
index c666ed8c3f..c666ed8c3f 100644
--- a/linux-user/host/mips/host-signal.h
+++ b/linux-user/include/host/mips/host-signal.h
diff --git a/linux-user/host/ppc/host-signal.h b/linux-user/include/host/ppc/host-signal.h
index 1d8e658ff7..1d8e658ff7 100644
--- a/linux-user/host/ppc/host-signal.h
+++ b/linux-user/include/host/ppc/host-signal.h
diff --git a/linux-user/host/ppc64/host-signal.h b/linux-user/include/host/ppc64/host-signal.h
index a353c22a90..a353c22a90 100644
--- a/linux-user/host/ppc64/host-signal.h
+++ b/linux-user/include/host/ppc64/host-signal.h
diff --git a/linux-user/host/riscv/host-signal.h b/linux-user/include/host/riscv/host-signal.h
index a4f170efb0..a4f170efb0 100644
--- a/linux-user/host/riscv/host-signal.h
+++ b/linux-user/include/host/riscv/host-signal.h
diff --git a/linux-user/host/s390/host-signal.h b/linux-user/include/host/s390/host-signal.h
index a524f2ab00..a524f2ab00 100644
--- a/linux-user/host/s390/host-signal.h
+++ b/linux-user/include/host/s390/host-signal.h
diff --git a/linux-user/host/s390x/host-signal.h b/linux-user/include/host/s390x/host-signal.h
index 0e83f9358d..0e83f9358d 100644
--- a/linux-user/host/s390x/host-signal.h
+++ b/linux-user/include/host/s390x/host-signal.h
diff --git a/linux-user/host/sparc/host-signal.h b/linux-user/include/host/sparc/host-signal.h
index 7342936071..7342936071 100644
--- a/linux-user/host/sparc/host-signal.h
+++ b/linux-user/include/host/sparc/host-signal.h
diff --git a/linux-user/host/sparc64/host-signal.h b/linux-user/include/host/sparc64/host-signal.h
index 1191fe2d40..1191fe2d40 100644
--- a/linux-user/host/sparc64/host-signal.h
+++ b/linux-user/include/host/sparc64/host-signal.h
diff --git a/linux-user/host/x32/host-signal.h b/linux-user/include/host/x32/host-signal.h
index 26800591d3..26800591d3 100644
--- a/linux-user/host/x32/host-signal.h
+++ b/linux-user/include/host/x32/host-signal.h
diff --git a/linux-user/host/x86_64/host-signal.h b/linux-user/include/host/x86_64/host-signal.h
index c71d597eb2..c71d597eb2 100644
--- a/linux-user/host/x86_64/host-signal.h
+++ b/linux-user/include/host/x86_64/host-signal.h
diff --git a/linux-user/special-errno.h b/linux-user/include/special-errno.h
index 4120455baa..4120455baa 100644
--- a/linux-user/special-errno.h
+++ b/linux-user/include/special-errno.h
diff --git a/linux-user/m68k/cpu_loop.c b/linux-user/m68k/cpu_loop.c
index 3181594414..928a18e3cf 100644
--- a/linux-user/m68k/cpu_loop.c
+++ b/linux-user/m68k/cpu_loop.c
@@ -29,7 +29,6 @@ void cpu_loop(CPUM68KState *env)
CPUState *cs = env_cpu(env);
int trapnr;
unsigned int n;
- target_siginfo_t info;
for(;;) {
cpu_exec_start(cs);
@@ -46,25 +45,13 @@ void cpu_loop(CPUM68KState *env)
case EXCP_ILLEGAL:
case EXCP_LINEA:
case EXCP_LINEF:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLOPN;
- info._sifields._sigfault._addr = env->pc;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc);
break;
case EXCP_CHK:
- info.si_signo = TARGET_SIGFPE;
- info.si_errno = 0;
- info.si_code = TARGET_FPE_INTOVF;
- info._sifields._sigfault._addr = env->pc;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->pc);
break;
case EXCP_DIV0:
- info.si_signo = TARGET_SIGFPE;
- info.si_errno = 0;
- info.si_code = TARGET_FPE_INTDIV;
- info._sifields._sigfault._addr = env->pc;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc);
break;
case EXCP_TRAP0:
{
@@ -91,10 +78,7 @@ void cpu_loop(CPUM68KState *env)
/* just indicate that signals should be handled asap */
break;
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
diff --git a/linux-user/m68k/target_structs.h b/linux-user/m68k/target_structs.h
index e373d481e1..3a06f373c3 100644
--- a/linux-user/m68k/target_structs.h
+++ b/linux-user/m68k/target_structs.h
@@ -1,58 +1 @@
-/*
- * m68k specific structures for linux-user
- *
- * Copyright (c) 2013 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef M68K_TARGET_STRUCTS_H
-#define M68K_TARGET_STRUCTS_H
-
-struct target_ipc_perm {
- abi_int __key; /* Key. */
- abi_uint uid; /* Owner's user ID. */
- abi_uint gid; /* Owner's group ID. */
- abi_uint cuid; /* Creator's user ID. */
- abi_uint cgid; /* Creator's group ID. */
- abi_ushort mode; /* Read/write permission. */
- abi_ushort __pad1;
- abi_ushort __seq; /* Sequence number. */
- abi_ushort __pad2;
- abi_ulong __unused1;
- abi_ulong __unused2;
-};
-
-struct target_shmid_ds {
- struct target_ipc_perm shm_perm; /* operation permission struct */
- abi_long shm_segsz; /* size of segment in bytes */
- abi_ulong shm_atime; /* time of last shmat() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused1;
-#endif
- abi_ulong shm_dtime; /* time of last shmdt() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused2;
-#endif
- abi_ulong shm_ctime; /* time of last change by shmctl() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused3;
-#endif
- abi_int shm_cpid; /* pid of creator */
- abi_int shm_lpid; /* pid of last shmop */
- abi_ulong shm_nattch; /* number of current attaches */
- abi_ulong __unused4;
- abi_ulong __unused5;
-};
-
-#endif
+#include "../generic/target_structs.h"
diff --git a/linux-user/meson.build b/linux-user/meson.build
index b2f4afd5e7..de4320af05 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -4,8 +4,8 @@ endif
linux_user_ss = ss.source_set()
-common_user_inc += include_directories('host/' / host_arch)
-common_user_inc += include_directories('.')
+common_user_inc += include_directories('include/host/' / host_arch)
+common_user_inc += include_directories('include')
linux_user_ss.add(files(
'elfload.c',
diff --git a/linux-user/microblaze/cpu_loop.c b/linux-user/microblaze/cpu_loop.c
index ff1fb26c8b..1a2556be2c 100644
--- a/linux-user/microblaze/cpu_loop.c
+++ b/linux-user/microblaze/cpu_loop.c
@@ -27,9 +27,8 @@
void cpu_loop(CPUMBState *env)
{
CPUState *cs = env_cpu(env);
- int trapnr, ret;
- target_siginfo_t info;
-
+ int trapnr, ret, si_code;
+
while (1) {
cpu_exec_start(cs);
trapnr = cpu_exec(cs);
@@ -38,8 +37,8 @@ void cpu_loop(CPUMBState *env)
switch (trapnr) {
case EXCP_INTERRUPT:
- /* just indicate that signals should be handled asap */
- break;
+ /* just indicate that signals should be handled asap */
+ break;
case EXCP_SYSCALL:
/* Return address is 4 bytes after the call. */
env->regs[14] += 4;
@@ -67,6 +66,7 @@ void cpu_loop(CPUMBState *env)
*/
env->regs[14] = env->pc;
break;
+
case EXCP_HW_EXCP:
env->regs[17] = env->pc + 4;
if (env->iflags & D_FLAG) {
@@ -74,42 +74,41 @@ void cpu_loop(CPUMBState *env)
env->pc -= 4;
/* FIXME: if branch was immed, replay the imm as well. */
}
-
env->iflags &= ~(IMM_FLAG | D_FLAG);
-
switch (env->esr & 31) {
- case ESR_EC_DIVZERO:
- info.si_signo = TARGET_SIGFPE;
- info.si_errno = 0;
- info.si_code = TARGET_FPE_FLTDIV;
- info._sifields._sigfault._addr = 0;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
- case ESR_EC_FPU:
- info.si_signo = TARGET_SIGFPE;
- info.si_errno = 0;
- if (env->fsr & FSR_IO) {
- info.si_code = TARGET_FPE_FLTINV;
- }
- if (env->fsr & FSR_DZ) {
- info.si_code = TARGET_FPE_FLTDIV;
- }
- info._sifields._sigfault._addr = 0;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
- default:
- fprintf(stderr, "Unhandled hw-exception: 0x%x\n",
- env->esr & ESR_EC_MASK);
- cpu_dump_state(cs, stderr, 0);
- exit(EXIT_FAILURE);
- break;
+ case ESR_EC_DIVZERO:
+ si_code = TARGET_FPE_INTDIV;
+ break;
+ case ESR_EC_FPU:
+ /*
+ * Note that the kernel passes along fsr as si_code
+ * if there's no recognized bit set. Possibly this
+ * implies that si_code is 0, but follow the structure.
+ */
+ si_code = env->fsr;
+ if (si_code & FSR_IO) {
+ si_code = TARGET_FPE_FLTINV;
+ } else if (si_code & FSR_OF) {
+ si_code = TARGET_FPE_FLTOVF;
+ } else if (si_code & FSR_UF) {
+ si_code = TARGET_FPE_FLTUND;
+ } else if (si_code & FSR_DZ) {
+ si_code = TARGET_FPE_FLTDIV;
+ } else if (si_code & FSR_DO) {
+ si_code = TARGET_FPE_FLTRES;
+ }
+ break;
+ default:
+ fprintf(stderr, "Unhandled hw-exception: 0x%x\n",
+ env->esr & ESR_EC_MASK);
+ cpu_dump_state(cs, stderr, 0);
+ exit(EXIT_FAILURE);
}
+ force_sig_fault(TARGET_SIGFPE, si_code, env->pc);
break;
+
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
diff --git a/linux-user/microblaze/target_structs.h b/linux-user/microblaze/target_structs.h
index d08f6a53a8..3a06f373c3 100644
--- a/linux-user/microblaze/target_structs.h
+++ b/linux-user/microblaze/target_structs.h
@@ -1,58 +1 @@
-/*
- * MicroBlaze specific structures for linux-user
- *
- * Copyright (c) 2013 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef MICROBLAZE_TARGET_STRUCTS_H
-#define MICROBLAZE_TARGET_STRUCTS_H
-
-struct target_ipc_perm {
- abi_int __key; /* Key. */
- abi_uint uid; /* Owner's user ID. */
- abi_uint gid; /* Owner's group ID. */
- abi_uint cuid; /* Creator's user ID. */
- abi_uint cgid; /* Creator's group ID. */
- abi_ushort mode; /* Read/write permission. */
- abi_ushort __pad1;
- abi_ushort __seq; /* Sequence number. */
- abi_ushort __pad2;
- abi_ulong __unused1;
- abi_ulong __unused2;
-};
-
-struct target_shmid_ds {
- struct target_ipc_perm shm_perm; /* operation permission struct */
- abi_long shm_segsz; /* size of segment in bytes */
- abi_ulong shm_atime; /* time of last shmat() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused1;
-#endif
- abi_ulong shm_dtime; /* time of last shmdt() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused2;
-#endif
- abi_ulong shm_ctime; /* time of last change by shmctl() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused3;
-#endif
- abi_int shm_cpid; /* pid of creator */
- abi_int shm_lpid; /* pid of last shmop */
- abi_ulong shm_nattch; /* number of current attaches */
- abi_ulong __unused4;
- abi_ulong __unused5;
-};
-
-#endif
+#include "../generic/target_structs.h"
diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c
index 32f9fc1c1c..9bb12a07ba 100644
--- a/linux-user/mips/cpu_loop.c
+++ b/linux-user/mips/cpu_loop.c
@@ -40,36 +40,32 @@ enum {
BRK_DIVZERO = 7
};
-static int do_break(CPUMIPSState *env, target_siginfo_t *info,
- unsigned int code)
+static void do_tr_or_bp(CPUMIPSState *env, unsigned int code, bool trap)
{
- int ret = -1;
+ target_ulong pc = env->active_tc.PC;
switch (code) {
case BRK_OVERFLOW:
+ force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, pc);
+ break;
case BRK_DIVZERO:
- info->si_signo = TARGET_SIGFPE;
- info->si_errno = 0;
- info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV;
- queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info);
- ret = 0;
+ force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, pc);
break;
default:
- info->si_signo = TARGET_SIGTRAP;
- info->si_errno = 0;
- queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info);
- ret = 0;
+ if (trap) {
+ force_sig(TARGET_SIGTRAP);
+ } else {
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, pc);
+ }
break;
}
-
- return ret;
}
void cpu_loop(CPUMIPSState *env)
{
CPUState *cs = env_cpu(env);
- target_siginfo_t info;
- int trapnr;
+ int trapnr, si_code;
+ unsigned int code;
abi_long ret;
# ifdef TARGET_ABI_MIPSO32
unsigned int syscall_num;
@@ -160,149 +156,53 @@ done_syscall:
break;
case EXCP_CpU:
case EXCP_RI:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = 0;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ case EXCP_DSPDIS:
+ force_sig(TARGET_SIGILL);
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
- case EXCP_DSPDIS:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLOPC;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT,
+ env->active_tc.PC);
break;
case EXCP_FPE:
- info.si_signo = TARGET_SIGFPE;
- info.si_errno = 0;
- info.si_code = TARGET_FPE_FLTUNK;
+ si_code = TARGET_FPE_FLTUNK;
if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) {
- info.si_code = TARGET_FPE_FLTINV;
+ si_code = TARGET_FPE_FLTINV;
} else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_DIV0) {
- info.si_code = TARGET_FPE_FLTDIV;
+ si_code = TARGET_FPE_FLTDIV;
} else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_OVERFLOW) {
- info.si_code = TARGET_FPE_FLTOVF;
+ si_code = TARGET_FPE_FLTOVF;
} else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_UNDERFLOW) {
- info.si_code = TARGET_FPE_FLTUND;
+ si_code = TARGET_FPE_FLTUND;
} else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INEXACT) {
- info.si_code = TARGET_FPE_FLTRES;
+ si_code = TARGET_FPE_FLTRES;
}
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGFPE, si_code, env->active_tc.PC);
break;
+
/* The code below was inspired by the MIPS Linux kernel trap
* handling code in arch/mips/kernel/traps.c.
*/
case EXCP_BREAK:
- {
- abi_ulong trap_instr;
- unsigned int code;
-
- if (env->hflags & MIPS_HFLAG_M16) {
- if (env->insn_flags & ASE_MICROMIPS) {
- /* microMIPS mode */
- ret = get_user_u16(trap_instr, env->active_tc.PC);
- if (ret != 0) {
- goto error;
- }
-
- if ((trap_instr >> 10) == 0x11) {
- /* 16-bit instruction */
- code = trap_instr & 0xf;
- } else {
- /* 32-bit instruction */
- abi_ulong instr_lo;
-
- ret = get_user_u16(instr_lo,
- env->active_tc.PC + 2);
- if (ret != 0) {
- goto error;
- }
- trap_instr = (trap_instr << 16) | instr_lo;
- code = ((trap_instr >> 6) & ((1 << 20) - 1));
- /* Unfortunately, microMIPS also suffers from
- the old assembler bug... */
- if (code >= (1 << 10)) {
- code >>= 10;
- }
- }
- } else {
- /* MIPS16e mode */
- ret = get_user_u16(trap_instr, env->active_tc.PC);
- if (ret != 0) {
- goto error;
- }
- code = (trap_instr >> 6) & 0x3f;
- }
- } else {
- ret = get_user_u32(trap_instr, env->active_tc.PC);
- if (ret != 0) {
- goto error;
- }
-
- /* As described in the original Linux kernel code, the
- * below checks on 'code' are to work around an old
- * assembly bug.
- */
- code = ((trap_instr >> 6) & ((1 << 20) - 1));
- if (code >= (1 << 10)) {
- code >>= 10;
- }
- }
-
- if (do_break(env, &info, code) != 0) {
- goto error;
- }
+ /*
+ * As described in the original Linux kernel code, the below
+ * checks on 'code' are to work around an old assembly bug.
+ */
+ code = env->error_code;
+ if (code >= (1 << 10)) {
+ code >>= 10;
}
+ do_tr_or_bp(env, code, false);
break;
case EXCP_TRAP:
- {
- abi_ulong trap_instr;
- unsigned int code = 0;
-
- if (env->hflags & MIPS_HFLAG_M16) {
- /* microMIPS mode */
- abi_ulong instr[2];
-
- ret = get_user_u16(instr[0], env->active_tc.PC) ||
- get_user_u16(instr[1], env->active_tc.PC + 2);
-
- trap_instr = (instr[0] << 16) | instr[1];
- } else {
- ret = get_user_u32(trap_instr, env->active_tc.PC);
- }
-
- if (ret != 0) {
- goto error;
- }
-
- /* The immediate versions don't provide a code. */
- if (!(trap_instr & 0xFC000000)) {
- if (env->hflags & MIPS_HFLAG_M16) {
- /* microMIPS mode */
- code = ((trap_instr >> 12) & ((1 << 4) - 1));
- } else {
- code = ((trap_instr >> 6) & ((1 << 10) - 1));
- }
- }
-
- if (do_break(env, &info, code) != 0) {
- goto error;
- }
- }
+ do_tr_or_bp(env, env->error_code, true);
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
break;
default:
-error:
EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
abort();
}
diff --git a/linux-user/nios2/target_structs.h b/linux-user/nios2/target_structs.h
index daa2886f98..3a06f373c3 100644
--- a/linux-user/nios2/target_structs.h
+++ b/linux-user/nios2/target_structs.h
@@ -1,58 +1 @@
-/*
- * Nios2 specific structures for linux-user
- *
- * Copyright (c) 2016 Marek Vasut <marex@denx.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef NIOS2_TARGET_STRUCTS_H
-#define NIOS2_TARGET_STRUCTS_H
-
-struct target_ipc_perm {
- abi_int __key; /* Key. */
- abi_uint uid; /* Owner's user ID. */
- abi_uint gid; /* Owner's group ID. */
- abi_uint cuid; /* Creator's user ID. */
- abi_uint cgid; /* Creator's group ID. */
- abi_ushort mode; /* Read/write permission. */
- abi_ushort __pad1;
- abi_ushort __seq; /* Sequence number. */
- abi_ushort __pad2;
- abi_ulong __unused1;
- abi_ulong __unused2;
-};
-
-struct target_shmid_ds {
- struct target_ipc_perm shm_perm; /* operation permission struct */
- abi_long shm_segsz; /* size of segment in bytes */
- abi_ulong shm_atime; /* time of last shmat() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused1;
-#endif
- abi_ulong shm_dtime; /* time of last shmdt() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused2;
-#endif
- abi_ulong shm_ctime; /* time of last change by shmctl() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused3;
-#endif
- abi_int shm_cpid; /* pid of creator */
- abi_int shm_lpid; /* pid of last shmop */
- abi_ulong shm_nattch; /* number of current attaches */
- abi_ulong __unused4;
- abi_ulong __unused5;
-};
-
-#endif
+#include "../generic/target_structs.h"
diff --git a/linux-user/openrisc/cpu_loop.c b/linux-user/openrisc/cpu_loop.c
index 592901a68b..7683bea064 100644
--- a/linux-user/openrisc/cpu_loop.c
+++ b/linux-user/openrisc/cpu_loop.c
@@ -29,7 +29,6 @@ void cpu_loop(CPUOpenRISCState *env)
CPUState *cs = env_cpu(env);
int trapnr;
abi_long ret;
- target_siginfo_t info;
for (;;) {
cpu_exec_start(cs);
@@ -55,27 +54,16 @@ void cpu_loop(CPUOpenRISCState *env)
}
break;
case EXCP_ALIGN:
- info.si_signo = TARGET_SIGBUS;
- info.si_errno = 0;
- info.si_code = TARGET_BUS_ADRALN;
- info._sifields._sigfault._addr = env->pc;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, env->eear);
break;
case EXCP_ILLEGAL:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLOPC;
- info._sifields._sigfault._addr = env->pc;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
break;
case EXCP_INTERRUPT:
/* We processed the pending cpu work above. */
break;
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
diff --git a/linux-user/openrisc/target_structs.h b/linux-user/openrisc/target_structs.h
index e98e2bc799..3a06f373c3 100644
--- a/linux-user/openrisc/target_structs.h
+++ b/linux-user/openrisc/target_structs.h
@@ -1,58 +1 @@
-/*
- * OpenRISC specific structures for linux-user
- *
- * Copyright (c) 2013 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef OPENRISC_TARGET_STRUCTS_H
-#define OPENRISC_TARGET_STRUCTS_H
-
-struct target_ipc_perm {
- abi_int __key; /* Key. */
- abi_uint uid; /* Owner's user ID. */
- abi_uint gid; /* Owner's group ID. */
- abi_uint cuid; /* Creator's user ID. */
- abi_uint cgid; /* Creator's group ID. */
- abi_ushort mode; /* Read/write permission. */
- abi_ushort __pad1;
- abi_ushort __seq; /* Sequence number. */
- abi_ushort __pad2;
- abi_ulong __unused1;
- abi_ulong __unused2;
-};
-
-struct target_shmid_ds {
- struct target_ipc_perm shm_perm; /* operation permission struct */
- abi_long shm_segsz; /* size of segment in bytes */
- abi_ulong shm_atime; /* time of last shmat() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused1;
-#endif
- abi_ulong shm_dtime; /* time of last shmdt() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused2;
-#endif
- abi_ulong shm_ctime; /* time of last change by shmctl() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused3;
-#endif
- abi_int shm_cpid; /* pid of creator */
- abi_int shm_lpid; /* pid of last shmop */
- abi_ulong shm_nattch; /* number of current attaches */
- abi_ulong __unused4;
- abi_ulong __unused5;
-};
-
-#endif
+#include "../generic/target_structs.h"
diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
index 30c82f2354..46e6ffd6d3 100644
--- a/linux-user/ppc/cpu_loop.c
+++ b/linux-user/ppc/cpu_loop.c
@@ -76,8 +76,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
void cpu_loop(CPUPPCState *env)
{
CPUState *cs = env_cpu(env);
- target_siginfo_t info;
- int trapnr;
+ int trapnr, si_signo, si_code;
target_ulong ret;
for(;;) {
@@ -102,61 +101,10 @@ void cpu_loop(CPUPPCState *env)
"Aborting\n");
break;
case POWERPC_EXCP_DSI: /* Data storage exception */
- /* XXX: check this. Seems bugged */
- switch (env->error_code & 0xFF000000) {
- case 0x40000000:
- case 0x42000000:
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_MAPERR;
- break;
- case 0x04000000:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLADR;
- break;
- case 0x08000000:
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_ACCERR;
- break;
- default:
- /* Let's send a regular segfault... */
- EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
- env->error_code);
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_MAPERR;
- break;
- }
- info._sifields._sigfault._addr = env->spr[SPR_DAR];
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
case POWERPC_EXCP_ISI: /* Instruction storage exception */
- /* XXX: check this */
- switch (env->error_code & 0xFF000000) {
- case 0x40000000:
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_MAPERR;
- break;
- case 0x10000000:
- case 0x08000000:
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_ACCERR;
- break;
- default:
- /* Let's send a regular segfault... */
- EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
- env->error_code);
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_MAPERR;
- break;
- }
- info._sifields._sigfault._addr = env->nip - 4;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ /* FIXME: handle maperr in ppc_cpu_record_sigsegv. */
+ force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
+ env->spr[SPR_DAR]);
break;
case POWERPC_EXCP_EXTERNAL: /* External input */
cpu_abort(cs, "External interrupt while in user mode. "
@@ -167,24 +115,23 @@ void cpu_loop(CPUPPCState *env)
/* XXX: check this */
switch (env->error_code & ~0xF) {
case POWERPC_EXCP_FP:
- info.si_signo = TARGET_SIGFPE;
- info.si_errno = 0;
+ si_signo = TARGET_SIGFPE;
switch (env->error_code & 0xF) {
case POWERPC_EXCP_FP_OX:
- info.si_code = TARGET_FPE_FLTOVF;
+ si_code = TARGET_FPE_FLTOVF;
break;
case POWERPC_EXCP_FP_UX:
- info.si_code = TARGET_FPE_FLTUND;
+ si_code = TARGET_FPE_FLTUND;
break;
case POWERPC_EXCP_FP_ZX:
case POWERPC_EXCP_FP_VXZDZ:
- info.si_code = TARGET_FPE_FLTDIV;
+ si_code = TARGET_FPE_FLTDIV;
break;
case POWERPC_EXCP_FP_XX:
- info.si_code = TARGET_FPE_FLTRES;
+ si_code = TARGET_FPE_FLTRES;
break;
case POWERPC_EXCP_FP_VXSOFT:
- info.si_code = TARGET_FPE_FLTINV;
+ si_code = TARGET_FPE_FLTINV;
break;
case POWERPC_EXCP_FP_VXSNAN:
case POWERPC_EXCP_FP_VXISI:
@@ -193,51 +140,50 @@ void cpu_loop(CPUPPCState *env)
case POWERPC_EXCP_FP_VXVC:
case POWERPC_EXCP_FP_VXSQRT:
case POWERPC_EXCP_FP_VXCVI:
- info.si_code = TARGET_FPE_FLTSUB;
+ si_code = TARGET_FPE_FLTSUB;
break;
default:
EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
env->error_code);
+ si_code = 0;
break;
}
break;
case POWERPC_EXCP_INVAL:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
+ si_signo = TARGET_SIGILL;
switch (env->error_code & 0xF) {
case POWERPC_EXCP_INVAL_INVAL:
- info.si_code = TARGET_ILL_ILLOPC;
+ si_code = TARGET_ILL_ILLOPC;
break;
case POWERPC_EXCP_INVAL_LSWX:
- info.si_code = TARGET_ILL_ILLOPN;
+ si_code = TARGET_ILL_ILLOPN;
break;
case POWERPC_EXCP_INVAL_SPR:
- info.si_code = TARGET_ILL_PRVREG;
+ si_code = TARGET_ILL_PRVREG;
break;
case POWERPC_EXCP_INVAL_FP:
- info.si_code = TARGET_ILL_COPROC;
+ si_code = TARGET_ILL_COPROC;
break;
default:
EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
env->error_code & 0xF);
- info.si_code = TARGET_ILL_ILLADR;
+ si_code = TARGET_ILL_ILLADR;
break;
}
break;
case POWERPC_EXCP_PRIV:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
+ si_signo = TARGET_SIGILL;
switch (env->error_code & 0xF) {
case POWERPC_EXCP_PRIV_OPC:
- info.si_code = TARGET_ILL_PRVOPC;
+ si_code = TARGET_ILL_PRVOPC;
break;
case POWERPC_EXCP_PRIV_REG:
- info.si_code = TARGET_ILL_PRVREG;
+ si_code = TARGET_ILL_PRVREG;
break;
default:
EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
env->error_code & 0xF);
- info.si_code = TARGET_ILL_PRVOPC;
+ si_code = TARGET_ILL_PRVOPC;
break;
}
break;
@@ -250,28 +196,19 @@ void cpu_loop(CPUPPCState *env)
env->error_code);
break;
}
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(si_signo, si_code, env->nip);
break;
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_COPROC;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
+ case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
+ case POWERPC_EXCP_VPU: /* Vector unavailable exception */
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_COPROC, env->nip);
break;
case POWERPC_EXCP_SYSCALL: /* System call exception */
case POWERPC_EXCP_SYSCALL_VECTORED:
cpu_abort(cs, "Syscall exception while in user mode. "
"Aborting\n");
break;
- case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_COPROC;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
case POWERPC_EXCP_DECR: /* Decrementer exception */
cpu_abort(cs, "Decrementer interrupt while in user mode. "
"Aborting\n");
@@ -292,13 +229,6 @@ void cpu_loop(CPUPPCState *env)
cpu_abort(cs, "Instruction TLB exception while in user mode. "
"Aborting\n");
break;
- case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_COPROC;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
cpu_abort(cs, "Embedded floating-point data IRQ not handled\n");
break;
@@ -355,13 +285,6 @@ void cpu_loop(CPUPPCState *env)
cpu_abort(cs, "Hypervisor instruction segment exception "
"while in user mode. Aborting\n");
break;
- case POWERPC_EXCP_VPU: /* Vector unavailable exception */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_COPROC;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
cpu_abort(cs, "Programmable interval timer interrupt "
"while in user mode. Aborting\n");
@@ -444,10 +367,7 @@ void cpu_loop(CPUPPCState *env)
env->gpr[3] = ret;
break;
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->nip);
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
diff --git a/linux-user/riscv/cpu_loop.c b/linux-user/riscv/cpu_loop.c
index 0cd8985cb8..26d446f323 100644
--- a/linux-user/riscv/cpu_loop.c
+++ b/linux-user/riscv/cpu_loop.c
@@ -30,8 +30,7 @@
void cpu_loop(CPURISCVState *env)
{
CPUState *cs = env_cpu(env);
- int trapnr, signum, sigcode;
- target_ulong sigaddr;
+ int trapnr;
target_ulong ret;
for (;;) {
@@ -40,10 +39,6 @@ void cpu_loop(CPURISCVState *env)
cpu_exec_end(cs);
process_queued_cpu_work(cs);
- signum = 0;
- sigcode = 0;
- sigaddr = 0;
-
switch (trapnr) {
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
@@ -79,39 +74,23 @@ void cpu_loop(CPURISCVState *env)
}
break;
case RISCV_EXCP_ILLEGAL_INST:
- signum = TARGET_SIGILL;
- sigcode = TARGET_ILL_ILLOPC;
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
break;
case RISCV_EXCP_BREAKPOINT:
- signum = TARGET_SIGTRAP;
- sigcode = TARGET_TRAP_BRKPT;
- sigaddr = env->pc;
+ case EXCP_DEBUG:
+ gdbstep:
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
break;
case RISCV_EXCP_SEMIHOST:
env->gpr[xA0] = do_common_semihosting(cs);
env->pc += 4;
break;
- case EXCP_DEBUG:
- gdbstep:
- signum = TARGET_SIGTRAP;
- sigcode = TARGET_TRAP_BRKPT;
- break;
default:
EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
trapnr);
exit(EXIT_FAILURE);
}
- if (signum) {
- target_siginfo_t info = {
- .si_signo = signum,
- .si_errno = 0,
- .si_code = sigcode,
- ._sifields._sigfault._addr = sigaddr
- };
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- }
-
process_pending_signals(env);
}
}
diff --git a/linux-user/riscv/target_structs.h b/linux-user/riscv/target_structs.h
index ea3e5ed17e..3a06f373c3 100644
--- a/linux-user/riscv/target_structs.h
+++ b/linux-user/riscv/target_structs.h
@@ -1,46 +1 @@
-/*
- * RISC-V specific structures for linux-user
- *
- * This is a copy of ../aarch64/target_structs.h atm.
- *
- */
-#ifndef RISCV_TARGET_STRUCTS_H
-#define RISCV_TARGET_STRUCTS_H
-
-struct target_ipc_perm {
- abi_int __key; /* Key. */
- abi_uint uid; /* Owner's user ID. */
- abi_uint gid; /* Owner's group ID. */
- abi_uint cuid; /* Creator's user ID. */
- abi_uint cgid; /* Creator's group ID. */
- abi_ushort mode; /* Read/write permission. */
- abi_ushort __pad1;
- abi_ushort __seq; /* Sequence number. */
- abi_ushort __pad2;
- abi_ulong __unused1;
- abi_ulong __unused2;
-};
-
-struct target_shmid_ds {
- struct target_ipc_perm shm_perm; /* operation permission struct */
- abi_long shm_segsz; /* size of segment in bytes */
- abi_ulong shm_atime; /* time of last shmat() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused1;
-#endif
- abi_ulong shm_dtime; /* time of last shmdt() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused2;
-#endif
- abi_ulong shm_ctime; /* time of last change by shmctl() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused3;
-#endif
- abi_int shm_cpid; /* pid of creator */
- abi_int shm_lpid; /* pid of last shmop */
- abi_ulong shm_nattch; /* number of current attaches */
- abi_ulong __unused4;
- abi_ulong __unused5;
-};
-
-#endif
+#include "../generic/target_structs.h"
diff --git a/linux-user/s390x/cpu_loop.c b/linux-user/s390x/cpu_loop.c
index ad0c3cd263..7901dfe6f5 100644
--- a/linux-user/s390x/cpu_loop.c
+++ b/linux-user/s390x/cpu_loop.c
@@ -58,7 +58,6 @@ void cpu_loop(CPUS390XState *env)
{
CPUState *cs = env_cpu(env);
int trapnr, n, sig;
- target_siginfo_t info;
target_ulong addr;
abi_long ret;
@@ -158,11 +157,7 @@ void cpu_loop(CPUS390XState *env)
*/
env->psw.addr += env->int_pgm_ilen;
do_signal:
- info.si_signo = sig;
- info.si_errno = 0;
- info.si_code = n;
- info._sifields._sigfault._addr = addr;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(sig, n, addr);
break;
case EXCP_ATOMIC:
diff --git a/linux-user/sh4/cpu_loop.c b/linux-user/sh4/cpu_loop.c
index 3290f6445c..1bd313cb19 100644
--- a/linux-user/sh4/cpu_loop.c
+++ b/linux-user/sh4/cpu_loop.c
@@ -28,7 +28,6 @@ void cpu_loop(CPUSH4State *env)
{
CPUState *cs = env_cpu(env);
int trapnr, ret;
- target_siginfo_t info;
while (1) {
bool arch_interrupt = true;
@@ -60,10 +59,7 @@ void cpu_loop(CPUSH4State *env)
/* just indicate that signals should be handled asap */
break;
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
diff --git a/linux-user/sh4/target_structs.h b/linux-user/sh4/target_structs.h
index 00ac39478b..3a06f373c3 100644
--- a/linux-user/sh4/target_structs.h
+++ b/linux-user/sh4/target_structs.h
@@ -1,58 +1 @@
-/*
- * SH4 specific structures for linux-user
- *
- * Copyright (c) 2013 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef SH4_TARGET_STRUCTS_H
-#define SH4_TARGET_STRUCTS_H
-
-struct target_ipc_perm {
- abi_int __key; /* Key. */
- abi_uint uid; /* Owner's user ID. */
- abi_uint gid; /* Owner's group ID. */
- abi_uint cuid; /* Creator's user ID. */
- abi_uint cgid; /* Creator's group ID. */
- abi_ushort mode; /* Read/write permission. */
- abi_ushort __pad1;
- abi_ushort __seq; /* Sequence number. */
- abi_ushort __pad2;
- abi_ulong __unused1;
- abi_ulong __unused2;
-};
-
-struct target_shmid_ds {
- struct target_ipc_perm shm_perm; /* operation permission struct */
- abi_long shm_segsz; /* size of segment in bytes */
- abi_ulong shm_atime; /* time of last shmat() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused1;
-#endif
- abi_ulong shm_dtime; /* time of last shmdt() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused2;
-#endif
- abi_ulong shm_ctime; /* time of last change by shmctl() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused3;
-#endif
- abi_int shm_cpid; /* pid of creator */
- abi_int shm_lpid; /* pid of last shmop */
- abi_ulong shm_nattch; /* number of current attaches */
- abi_ulong __unused4;
- abi_ulong __unused5;
-};
-
-#endif
+#include "../generic/target_structs.h"
diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c
index 8765ab6020..baf3d9ae01 100644
--- a/linux-user/sparc/cpu_loop.c
+++ b/linux-user/sparc/cpu_loop.c
@@ -155,7 +155,6 @@ void cpu_loop (CPUSPARCState *env)
CPUState *cs = env_cpu(env);
int trapnr;
abi_long ret;
- target_siginfo_t info;
while (1) {
cpu_exec_start(cs);
@@ -241,19 +240,10 @@ void cpu_loop (CPUSPARCState *env)
/* just indicate that signals should be handled asap */
break;
case TT_ILL_INSN:
- {
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLOPC;
- info._sifields._sigfault._addr = env->pc;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- }
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
break;
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ce9d64896c..5950222a77 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6444,11 +6444,15 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
int deathsig;
ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig,
arg3, arg4, arg5));
- if (!is_error(ret) && arg2 && put_user_s32(deathsig, arg2)) {
+ if (!is_error(ret) &&
+ put_user_s32(host_to_target_signal(deathsig), arg2)) {
return -TARGET_EFAULT;
}
return ret;
}
+ case PR_SET_PDEATHSIG:
+ return get_errno(prctl(PR_SET_PDEATHSIG, target_to_host_signal(arg2),
+ arg3, arg4, arg5));
case PR_GET_NAME:
{
void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
@@ -6500,10 +6504,15 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
case PR_SET_UNALIGN:
return do_prctl_set_unalign(env, arg2);
+ case PR_CAP_AMBIENT:
+ case PR_CAPBSET_READ:
+ case PR_CAPBSET_DROP:
case PR_GET_DUMPABLE:
case PR_SET_DUMPABLE:
case PR_GET_KEEPCAPS:
case PR_SET_KEEPCAPS:
+ case PR_GET_SECUREBITS:
+ case PR_SET_SECUREBITS:
case PR_GET_TIMING:
case PR_SET_TIMING:
case PR_GET_TIMERSLACK:
@@ -6927,6 +6936,14 @@ typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr);
typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl);
#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
+struct target_oabi_flock64 {
+ abi_short l_type;
+ abi_short l_whence;
+ abi_llong l_start;
+ abi_llong l_len;
+ abi_int l_pid;
+} QEMU_PACKED;
+
static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl,
abi_ulong target_flock_addr)
{
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index cca561f622..f23f0a2178 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -688,7 +688,7 @@ typedef struct target_siginfo {
#define TARGET_FPE_FLTINV (7) /* floating point invalid operation */
#define TARGET_FPE_FLTSUB (8) /* subscript out of range */
#define TARGET_FPE_FLTUNK (14) /* undiagnosed fp exception */
-#define TARGET_NSIGFPE 15
+#define TARGET_FPE_CONDTRAP (15) /* trap on condition */
/*
* SIGSEGV si_codes
@@ -715,6 +715,7 @@ typedef struct target_siginfo {
#define TARGET_TRAP_TRACE (2) /* process trace trap */
#define TARGET_TRAP_BRANCH (3) /* process taken branch trap */
#define TARGET_TRAP_HWBKPT (4) /* hardware breakpoint/watchpoint */
+#define TARGET_TRAP_UNK (5) /* undiagnosed trap */
struct target_rlimit {
abi_ulong rlim_cur;
diff --git a/linux-user/x86_64/target_structs.h b/linux-user/x86_64/target_structs.h
index ce367b253b..f1181383c4 100644
--- a/linux-user/x86_64/target_structs.h
+++ b/linux-user/x86_64/target_structs.h
@@ -19,41 +19,7 @@
#ifndef X86_64_TARGET_STRUCTS_H
#define X86_64_TARGET_STRUCTS_H
-struct target_ipc_perm {
- abi_int __key; /* Key. */
- abi_uint uid; /* Owner's user ID. */
- abi_uint gid; /* Owner's group ID. */
- abi_uint cuid; /* Creator's user ID. */
- abi_uint cgid; /* Creator's group ID. */
- abi_ushort mode; /* Read/write permission. */
- abi_ushort __pad1;
- abi_ushort __seq; /* Sequence number. */
- abi_ushort __pad2;
- abi_ulong __unused1;
- abi_ulong __unused2;
-};
-
-struct target_shmid_ds {
- struct target_ipc_perm shm_perm; /* operation permission struct */
- abi_long shm_segsz; /* size of segment in bytes */
- abi_ulong shm_atime; /* time of last shmat() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused1;
-#endif
- abi_ulong shm_dtime; /* time of last shmdt() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused2;
-#endif
- abi_ulong shm_ctime; /* time of last change by shmctl() */
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused3;
-#endif
- abi_int shm_cpid; /* pid of creator */
- abi_int shm_lpid; /* pid of last shmop */
- abi_ulong shm_nattch; /* number of current attaches */
- abi_ulong __unused4;
- abi_ulong __unused5;
-};
+#include "../generic/target_structs.h"
/* The x86 definition differs from the generic one in that the
* two padding fields exist whether the ABI is 32 bits or 64 bits.
diff --git a/linux-user/xtensa/cpu_loop.c b/linux-user/xtensa/cpu_loop.c
index 6bc6d6dee6..d51ce05392 100644
--- a/linux-user/xtensa/cpu_loop.c
+++ b/linux-user/xtensa/cpu_loop.c
@@ -126,7 +126,6 @@ static void xtensa_underflow12(CPUXtensaState *env)
void cpu_loop(CPUXtensaState *env)
{
CPUState *cs = env_cpu(env);
- target_siginfo_t info;
abi_ulong ret;
int trapnr;
@@ -163,14 +162,12 @@ void cpu_loop(CPUXtensaState *env)
case EXC_USER:
switch (env->sregs[EXCCAUSE]) {
case ILLEGAL_INSTRUCTION_CAUSE:
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC,
+ env->sregs[EPC1]);
+ break;
case PRIVILEGED_CAUSE:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code =
- env->sregs[EXCCAUSE] == ILLEGAL_INSTRUCTION_CAUSE ?
- TARGET_ILL_ILLOPC : TARGET_ILL_PRVOPC;
- info._sifields._sigfault._addr = env->sregs[EPC1];
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC,
+ env->sregs[EPC1]);
break;
case SYSCALL_CAUSE:
@@ -219,11 +216,8 @@ void cpu_loop(CPUXtensaState *env)
break;
case INTEGER_DIVIDE_BY_ZERO_CAUSE:
- info.si_signo = TARGET_SIGFPE;
- info.si_errno = 0;
- info.si_code = TARGET_FPE_INTDIV;
- info._sifields._sigfault._addr = env->sregs[EPC1];
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV,
+ env->sregs[EPC1]);
break;
default:
@@ -232,10 +226,8 @@ void cpu_loop(CPUXtensaState *env)
}
break;
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT,
+ env->sregs[EPC1]);
break;
case EXC_DEBUG:
default:
diff --git a/meson.build b/meson.build
index c1b1db1e28..762d7cee85 100644
--- a/meson.build
+++ b/meson.build
@@ -238,6 +238,7 @@ endif
# Target-specific checks and dependencies #
###########################################
+# Fuzzing
if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \
not cc.links('''
#include <stdint.h>
@@ -249,6 +250,7 @@ if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \
error('Your compiler does not support -fsanitize=fuzzer')
endif
+# Tracing backends
if 'ftrace' in get_option('trace_backends') and targetos != 'linux'
error('ftrace is supported only on Linux')
endif
@@ -262,6 +264,7 @@ if 'syslog' in get_option('trace_backends') and not cc.compiles('''
error('syslog is not supported on this system')
endif
+# Miscellaneous Linux-only features
if targetos != 'linux' and get_option('mpath').enabled()
error('Multipath is supported only on Linux')
endif
@@ -271,6 +274,7 @@ if targetos != 'linux' and get_option('multiprocess').enabled()
endif
multiprocess_allowed = targetos == 'linux' and not get_option('multiprocess').disabled()
+# Target-specific libraries and flags
libm = cc.find_library('m', required: false)
threads = dependency('threads')
util = cc.find_library('util', required: false)
@@ -311,6 +315,7 @@ elif targetos == 'openbsd'
endif
endif
+# Target-specific configuration of accelerators
accelerators = []
if not get_option('kvm').disabled() and targetos == 'linux'
accelerators += 'CONFIG_KVM'
@@ -2028,6 +2033,18 @@ config_all += {
'CONFIG_ALL': true,
}
+target_configs_h = []
+foreach target: target_dirs
+ target_configs_h += config_target_h[target]
+ target_configs_h += config_devices_h.get(target, [])
+endforeach
+genh += custom_target('config-poison.h',
+ input: [target_configs_h],
+ output: 'config-poison.h',
+ capture: true,
+ command: [find_program('scripts/make-config-poison.sh'),
+ target_configs_h])
+
##############
# Submodules #
##############
@@ -2399,7 +2416,6 @@ blockdev_ss = ss.source_set()
block_ss = ss.source_set()
chardev_ss = ss.source_set()
common_ss = ss.source_set()
-common_user_ss = ss.source_set()
crypto_ss = ss.source_set()
hwcore_ss = ss.source_set()
io_ss = ss.source_set()
@@ -2651,17 +2667,6 @@ subdir('common-user')
subdir('bsd-user')
subdir('linux-user')
-common_user_ss = common_user_ss.apply(config_all, strict: false)
-common_user = static_library('common-user',
- sources: common_user_ss.sources(),
- dependencies: common_user_ss.dependencies(),
- include_directories: common_user_inc,
- name_suffix: 'fa',
- build_by_default: false)
-common_user = declare_dependency(link_with: common_user)
-
-user_ss.add(common_user)
-
# needed for fuzzing binaries
subdir('tests/qtest/libqos')
subdir('tests/qtest/fuzz')
@@ -2861,8 +2866,10 @@ common_ss.add(hwcore)
# Targets #
###########
+emulator_modules = []
foreach m : block_mods + softmmu_mods
- shared_module(m.name(),
+ emulator_modules += shared_module(m.name(),
+ build_by_default: true,
name_prefix: '',
link_whole: m,
install: true,
@@ -2879,6 +2886,7 @@ common_all = common_ss.apply(config_all, strict: false)
common_all = static_library('common',
build_by_default: false,
sources: common_all.sources() + genh,
+ include_directories: common_user_inc,
implicit_include_directories: false,
dependencies: common_all.dependencies(),
name_suffix: 'fa')
@@ -2919,6 +2927,7 @@ foreach target : target_dirs
else
abi = config_target['TARGET_ABI_DIR']
target_type='user'
+ target_inc += common_user_inc
qemu_target_name = 'qemu-' + target_name
if target_base_arch in target_user_arch
t = target_user_arch[target_base_arch].apply(config_target, strict: false)
@@ -2927,7 +2936,6 @@ foreach target : target_dirs
endif
if 'CONFIG_LINUX_USER' in config_target
base_dir = 'linux-user'
- target_inc += include_directories('linux-user/host/' / host_arch)
endif
if 'CONFIG_BSD_USER' in config_target
base_dir = 'bsd-user'
@@ -3456,7 +3464,6 @@ if spice_protocol.found()
summary_info += {' spice server support': spice}
endif
summary_info += {'rbd support': rbd}
-summary_info += {'xfsctl support': config_host.has_key('CONFIG_XFS')}
summary_info += {'smartcard support': cacard}
summary_info += {'U2F support': u2f}
summary_info += {'libusb': libusb}
diff --git a/migration/rdma.c b/migration/rdma.c
index f5d3bbe7e9..c7c7a38487 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -3161,14 +3161,14 @@ static void qio_channel_rdma_set_aio_fd_handler(QIOChannel *ioc,
QIOChannelRDMA *rioc = QIO_CHANNEL_RDMA(ioc);
if (io_read) {
aio_set_fd_handler(ctx, rioc->rdmain->recv_comp_channel->fd,
- false, io_read, io_write, NULL, opaque);
+ false, io_read, io_write, NULL, NULL, opaque);
aio_set_fd_handler(ctx, rioc->rdmain->send_comp_channel->fd,
- false, io_read, io_write, NULL, opaque);
+ false, io_read, io_write, NULL, NULL, opaque);
} else {
aio_set_fd_handler(ctx, rioc->rdmaout->recv_comp_channel->fd,
- false, io_read, io_write, NULL, opaque);
+ false, io_read, io_write, NULL, NULL, opaque);
aio_set_fd_handler(ctx, rioc->rdmaout->send_comp_channel->fd,
- false, io_read, io_write, NULL, opaque);
+ false, io_read, io_write, NULL, NULL, opaque);
}
}
diff --git a/pc-bios/README b/pc-bios/README
index c51ae58824..ba6c15e769 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -14,7 +14,7 @@
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
implementation for certain IBM POWER hardware. The sources are at
https://github.com/aik/SLOF, and the image currently in qemu is
- built from git tag qemu-slof-20211112.
+ built from git tag qemu-slof-20220110.
- VOF (Virtual Open Firmware) is a minimalistic firmware to work with
-machine pseries,x-vof=on. When enabled, the firmware acts as a slim shim and
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index cee9d2c63b..0eb68efc7b 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -44,8 +44,6 @@ build-all: s390-ccw.img s390-netboot.img
s390-ccw.elf: $(OBJECTS)
$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS),"BUILD","$(TARGET_DIR)$@")
-STRIP ?= strip
-
s390-ccw.img: s390-ccw.elf
$(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,"STRIP","$(TARGET_DIR)$@")
diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin
index 046ca63709..cbbe23e910 100644
--- a/pc-bios/slof.bin
+++ b/pc-bios/slof.bin
Binary files differ
diff --git a/plugins/meson.build b/plugins/meson.build
index b3de57853b..fa12047327 100644
--- a/plugins/meson.build
+++ b/plugins/meson.build
@@ -1,10 +1,15 @@
plugin_ldflags = []
# Modules need more symbols than just those in plugins/qemu-plugins.symbols
if not enable_modules
- if 'CONFIG_HAS_LD_DYNAMIC_LIST' in config_host
- plugin_ldflags = ['-Wl,--dynamic-list=qemu-plugins-ld.symbols']
- elif 'CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST' in config_host
- plugin_ldflags = ['-Wl,-exported_symbols_list,qemu-plugins-ld64.symbols']
+ if targetos == 'darwin'
+ qemu_plugins_symbols_list = configure_file(
+ input: files('qemu-plugins.symbols'),
+ output: 'qemu-plugins-ld64.symbols',
+ capture: true,
+ command: ['sed', '-ne', 's/^[[:space:]]*\\(qemu_.*\\);/_\\1/p', '@INPUT@'])
+ plugin_ldflags = ['-Wl,-exported_symbols_list,plugins/qemu-plugins-ld64.symbols']
+ else
+ plugin_ldflags = ['-Xlinker', '--dynamic-list=' + (meson.project_source_root() / 'plugins/qemu-plugins.symbols')]
endif
endif
diff --git a/python/qemu/aqmp/aqmp_tui.py b/python/qemu/aqmp/aqmp_tui.py
index a2929f771c..f1e926dd75 100644
--- a/python/qemu/aqmp/aqmp_tui.py
+++ b/python/qemu/aqmp/aqmp_tui.py
@@ -35,7 +35,8 @@ from pygments import token as Token
import urwid
import urwid_readline
-from ..qmp import QEMUMonitorProtocol, QMPBadPortError
+from qemu.qmp import QEMUMonitorProtocol, QMPBadPortError
+
from .error import ProtocolError
from .message import DeserializationError, Message, UnexpectedTypeError
from .protocol import ConnectError, Runstate
diff --git a/python/qemu/aqmp/protocol.py b/python/qemu/aqmp/protocol.py
index 5190b33b13..c4fbe35a0e 100644
--- a/python/qemu/aqmp/protocol.py
+++ b/python/qemu/aqmp/protocol.py
@@ -43,8 +43,8 @@ from .util import (
T = TypeVar('T')
+_U = TypeVar('_U')
_TaskFN = Callable[[], Awaitable[None]] # aka ``async def func() -> None``
-_FutureT = TypeVar('_FutureT', bound=Optional['asyncio.Future[Any]'])
class Runstate(Enum):
@@ -591,7 +591,8 @@ class AsyncProtocol(Generic[T]):
"""
Fully reset this object to a clean state and return to `IDLE`.
"""
- def _paranoid_task_erase(task: _FutureT) -> Optional[_FutureT]:
+ def _paranoid_task_erase(task: Optional['asyncio.Future[_U]']
+ ) -> Optional['asyncio.Future[_U]']:
# Help to erase a task, ENSURING it is fully quiesced first.
assert (task is None) or task.done()
return None if (task and task.done()) else task
diff --git a/python/qemu/qmp/qom_common.py b/python/qemu/qmp/qom_common.py
index a59ae1a2a1..2e4c741f77 100644
--- a/python/qemu/qmp/qom_common.py
+++ b/python/qemu/qmp/qom_common.py
@@ -30,10 +30,6 @@ from typing import (
from . import QEMUMonitorProtocol, QMPError
-# The following is needed only for a type alias.
-Subparsers = argparse._SubParsersAction # pylint: disable=protected-access
-
-
class ObjectPropertyInfo:
"""
Represents the return type from e.g. qom-list.
@@ -89,7 +85,7 @@ class QOMCommand:
self.qmp.connect()
@classmethod
- def register(cls, subparsers: Subparsers) -> None:
+ def register(cls, subparsers: Any) -> None:
"""
Register this command with the argument parser.
diff --git a/qapi/block-core.json b/qapi/block-core.json
index bd0b285245..9a5a3641d0 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1878,14 +1878,11 @@
#
# @resize: This permission is required to change the size of a block node.
#
-# @graph-mod: This permission is required to change the node that this
-# BdrvChild points to.
-#
# Since: 4.0
##
{ 'enum': 'BlockPermission',
- 'data': [ 'consistent-read', 'write', 'write-unchanged', 'resize',
- 'graph-mod' ] }
+ 'data': [ 'consistent-read', 'write', 'write-unchanged', 'resize' ] }
+
##
# @XDbgBlockGraphEdge:
#
diff --git a/qapi/block-export.json b/qapi/block-export.json
index c1b92ce1c1..f9ce79a974 100644
--- a/qapi/block-export.json
+++ b/qapi/block-export.json
@@ -277,7 +277,8 @@
# Since: 4.2
##
{ 'enum': 'BlockExportType',
- 'data': [ 'nbd', 'vhost-user-blk',
+ 'data': [ 'nbd',
+ { 'name': 'vhost-user-blk', 'if': 'CONFIG_VHOST_USER_BLK_SERVER' },
{ 'name': 'fuse', 'if': 'CONFIG_FUSE' } ] }
##
@@ -319,7 +320,8 @@
'discriminator': 'type',
'data': {
'nbd': 'BlockExportOptionsNbd',
- 'vhost-user-blk': 'BlockExportOptionsVhostUserBlk',
+ 'vhost-user-blk': { 'type': 'BlockExportOptionsVhostUserBlk',
+ 'if': 'CONFIG_VHOST_USER_BLK_SERVER' },
'fuse': { 'type': 'BlockExportOptionsFuse',
'if': 'CONFIG_FUSE' }
} }
diff --git a/qapi/qdev.json b/qapi/qdev.json
index 69656b14df..26cd10106b 100644
--- a/qapi/qdev.json
+++ b/qapi/qdev.json
@@ -44,6 +44,9 @@
# @json-cli: If present, the "-device" command line option supports JSON
# syntax with a structure identical to the arguments of this
# command.
+# @json-cli-hotplug: If present, the "-device" command line option supports JSON
+# syntax without the reference counting leak that broke
+# hot-unplug
#
# Notes:
#
@@ -74,7 +77,7 @@
{ 'command': 'device_add',
'data': {'driver': 'str', '*bus': 'str', '*id': 'str'},
'gen': false, # so we can get the additional arguments
- 'features': ['json-cli'] }
+ 'features': ['json-cli', 'json-cli-hotplug'] }
##
# @device_del:
diff --git a/qapi/ui.json b/qapi/ui.json
index 2b4371da37..9354f4c467 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -905,7 +905,7 @@
##
{ 'enum' : 'InputButton',
'data' : [ 'left', 'middle', 'right', 'wheel-up', 'wheel-down', 'side',
- 'extra' ] }
+ 'extra', 'wheel-left', 'wheel-right' ] }
##
# @InputAxis:
diff --git a/qemu-edid.c b/qemu-edid.c
index c3a9fba10d..20c958d9c7 100644
--- a/qemu-edid.c
+++ b/qemu-edid.c
@@ -10,8 +10,8 @@
#include "hw/display/edid.h"
static qemu_edid_info info = {
- .prefx = 1024,
- .prefy = 768,
+ .prefx = 1280,
+ .prefy = 800,
};
static void usage(FILE *out)
diff --git a/qemu-img.c b/qemu-img.c
index 21ba1e6800..6fe2466032 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1171,19 +1171,34 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum,
}
}
+ if (i == n) {
+ /*
+ * The whole buf is the same.
+ * No reason to split it into chunks, so return now.
+ */
+ *pnum = i;
+ return !is_zero;
+ }
+
tail = (sector_num + i) & (alignment - 1);
if (tail) {
if (is_zero && i <= tail) {
- /* treat unallocated areas which only consist
- * of a small tail as allocated. */
+ /*
+ * For sure next sector after i is data, and it will rewrite this
+ * tail anyway due to RMW. So, let's just write data now.
+ */
is_zero = false;
}
if (!is_zero) {
- /* align up end offset of allocated areas. */
+ /* If possible, align up end offset of allocated areas. */
i += alignment - tail;
i = MIN(i, n);
} else {
- /* align down end offset of zero areas. */
+ /*
+ * For sure next sector after i is data, and it will rewrite this
+ * tail anyway due to RMW. Better is avoid RMW and write zeroes up
+ * to aligned bound.
+ */
i -= tail;
}
}
diff --git a/roms/SLOF b/roms/SLOF
-Subproject a6906b024c6cca5a86496f51eb4bfee3a0c3614
+Subproject 5b4c5acdcd552a4e1796aeca6bb700f6cbb0282
diff --git a/scripts/ci/org.centos/stream/8/x86_64/configure b/scripts/ci/org.centos/stream/8/x86_64/configure
index 048e80dc49..e05f2fddcc 100755
--- a/scripts/ci/org.centos/stream/8/x86_64/configure
+++ b/scripts/ci/org.centos/stream/8/x86_64/configure
@@ -151,7 +151,6 @@
--disable-whpx \
--disable-xen \
--disable-xen-pci-passthrough \
---disable-xfsctl \
--disable-xkbcommon \
--disable-zstd \
--enable-attr \
diff --git a/scripts/coverity-scan/run-coverity-scan b/scripts/coverity-scan/run-coverity-scan
index 7395bbfad4..6d443250a9 100755
--- a/scripts/coverity-scan/run-coverity-scan
+++ b/scripts/coverity-scan/run-coverity-scan
@@ -398,7 +398,7 @@ echo "Configuring..."
--enable-xen --enable-brlapi \
--enable-linux-aio --enable-attr \
--enable-cap-ng --enable-trace-backends=log --enable-spice --enable-rbd \
- --enable-xfsctl --enable-libusb --enable-usb-redir \
+ --enable-libusb --enable-usb-redir \
--enable-libiscsi --enable-libnfs --enable-seccomp \
--enable-tpm --enable-libssh --enable-lzo --enable-snappy --enable-bzip2 \
--enable-numa --enable-rdma --enable-smartcard --enable-virglrenderer \
diff --git a/scripts/make-config-poison.sh b/scripts/make-config-poison.sh
new file mode 100755
index 0000000000..d222a04304
--- /dev/null
+++ b/scripts/make-config-poison.sh
@@ -0,0 +1,16 @@
+#! /bin/sh
+
+if test $# = 0; then
+ exit 0
+fi
+
+# Create list of config switches that should be poisoned in common code...
+# but filter out CONFIG_TCG and CONFIG_USER_ONLY which are special.
+exec sed -n \
+ -e' /CONFIG_TCG/d' \
+ -e '/CONFIG_USER_ONLY/d' \
+ -e '/^#define / {' \
+ -e 's///' \
+ -e 's/ .*//' \
+ -e 's/^/#pragma GCC poison /p' \
+ -e '}' "$@"
diff --git a/scripts/meson-buildoptions.py b/scripts/meson-buildoptions.py
index 96969d89ee..98ae944148 100755
--- a/scripts/meson-buildoptions.py
+++ b/scripts/meson-buildoptions.py
@@ -36,6 +36,10 @@ SKIP_OPTIONS = {
"trace_file",
}
+BUILTIN_OPTIONS = {
+ "strip",
+}
+
LINE_WIDTH = 76
@@ -90,14 +94,17 @@ def allow_arg(opt):
return not (set(opt["choices"]) <= {"auto", "disabled", "enabled"})
+def filter_options(json):
+ if ":" in json["name"]:
+ return False
+ if json["section"] == "user":
+ return json["name"] not in SKIP_OPTIONS
+ else:
+ return json["name"] in BUILTIN_OPTIONS
+
+
def load_options(json):
- json = [
- x
- for x in json
- if x["section"] == "user"
- and ":" not in x["name"]
- and x["name"] not in SKIP_OPTIONS
- ]
+ json = [x for x in json if filter_options(x)]
return sorted(json, key=lambda x: x["name"])
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index 50bd7bed4d..a4af02c527 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -13,6 +13,7 @@ meson_options_help() {
printf "%s\n" ' jemalloc/system/tcmalloc)'
printf "%s\n" ' --enable-slirp[=CHOICE] Whether and how to find the slirp library'
printf "%s\n" ' (choices: auto/disabled/enabled/internal/system)'
+ printf "%s\n" ' --enable-strip Strip targets on install'
printf "%s\n" ' --enable-tcg-interpreter TCG with bytecode interpreter (slow)'
printf "%s\n" ' --enable-trace-backends=CHOICE'
printf "%s\n" ' Set available tracing backends [log] (choices:'
@@ -237,6 +238,8 @@ _meson_option_parse() {
--disable-spice) printf "%s" -Dspice=disabled ;;
--enable-spice-protocol) printf "%s" -Dspice_protocol=enabled ;;
--disable-spice-protocol) printf "%s" -Dspice_protocol=disabled ;;
+ --enable-strip) printf "%s" -Dstrip=true ;;
+ --disable-strip) printf "%s" -Dstrip=false ;;
--enable-tcg) printf "%s" -Dtcg=enabled ;;
--disable-tcg) printf "%s" -Dtcg=disabled ;;
--enable-tcg-interpreter) printf "%s" -Dtcg_interpreter=true ;;
diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py
index da6acf050d..42288a3cfb 100755
--- a/scripts/render_block_graph.py
+++ b/scripts/render_block_graph.py
@@ -35,7 +35,6 @@ def perm(arr):
s = 'w' if 'write' in arr else '_'
s += 'r' if 'consistent-read' in arr else '_'
s += 'u' if 'write-unchanged' in arr else '_'
- s += 'g' if 'graph-mod' in arr else '_'
s += 's' if 'resize' in arr else '_'
return s
diff --git a/scripts/simplebench/bench-example.py b/scripts/simplebench/bench-example.py
index 4864435f39..fc370691e0 100644
--- a/scripts/simplebench/bench-example.py
+++ b/scripts/simplebench/bench-example.py
@@ -25,7 +25,7 @@ from bench_block_job import bench_block_copy, drv_file, drv_nbd
def bench_func(env, case):
""" Handle one "cell" of benchmarking table. """
- return bench_block_copy(env['qemu_binary'], env['cmd'], {}
+ return bench_block_copy(env['qemu_binary'], env['cmd'], {},
case['source'], case['target'])
diff --git a/softmmu/vl.c b/softmmu/vl.c
index a8cad43691..5e1b35ba48 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2684,6 +2684,7 @@ static void qemu_create_cli_devices(void)
qemu_opts_foreach(qemu_find_opts("device"),
device_init_func, NULL, &error_fatal);
QTAILQ_FOREACH(opt, &device_opts, next) {
+ DeviceState *dev;
loc_push_restore(&opt->loc);
/*
* TODO Eventually we should call qmp_device_add() here to make sure it
@@ -2692,7 +2693,8 @@ static void qemu_create_cli_devices(void)
* from the start, so call qdev_device_add_from_qdict() directly for
* now.
*/
- qdev_device_add_from_qdict(opt->opts, true, &error_fatal);
+ dev = qdev_device_add_from_qdict(opt->opts, true, &error_fatal);
+ object_unref(OBJECT(dev));
loc_pop(&opt->loc);
}
rom_reset_order_override();
@@ -2887,7 +2889,9 @@ void qemu_init(int argc, char **argv, char **envp)
break;
}
case QEMU_OPTION_drive:
- if (drive_def(optarg) == NULL) {
+ opts = qemu_opts_parse_noisily(qemu_find_opts("drive"),
+ optarg, false);
+ if (opts == NULL) {
exit(1);
}
break;
diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c
index 52cf17e8ac..9d76d1114d 100644
--- a/storage-daemon/qemu-storage-daemon.c
+++ b/storage-daemon/qemu-storage-daemon.c
@@ -104,6 +104,19 @@ static void help(void)
" export the specified block node over FUSE\n"
"\n"
#endif /* CONFIG_FUSE */
+#ifdef CONFIG_VHOST_USER_BLK_SERVER
+" --export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,\n"
+" addr.type=unix,addr.path=<socket-path>[,writable=on|off]\n"
+" [,logical-block-size=<block-size>][,num-queues=<num-queues>]\n"
+" export the specified block node as a\n"
+" vhost-user-blk device over UNIX domain socket\n"
+" --export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,\n"
+" fd,addr.str=<fd>[,writable=on|off]\n"
+" [,logical-block-size=<block-size>][,num-queues=<num-queues>]\n"
+" export the specified block node as a\n"
+" vhost-user-blk device over file descriptor\n"
+"\n"
+#endif /* CONFIG_VHOST_USER_BLK_SERVER */
" --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n"
" configure a QMP monitor\n"
"\n"
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 04f2b790c9..9911d7c871 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1455,6 +1455,9 @@ typedef struct CPUX86State {
SegmentCache idt; /* only base and limit are used */
target_ulong cr[5]; /* NOTE: cr1 is unused */
+
+ bool pdptrs_valid;
+ uint64_t pdptrs[4];
int32_t a20_mask;
BNDReg bnd_regs[4];
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 13f8e30c2a..2c8feb4a6f 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -124,6 +124,7 @@ static uint32_t num_architectural_pmu_fixed_counters;
static int has_xsave;
static int has_xcrs;
static int has_pit_state2;
+static int has_sregs2;
static int has_exception_payload;
static bool has_msr_mcg_ext_ctl;
@@ -2324,6 +2325,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
has_xsave = kvm_check_extension(s, KVM_CAP_XSAVE);
has_xcrs = kvm_check_extension(s, KVM_CAP_XCRS);
has_pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2);
+ has_sregs2 = kvm_check_extension(s, KVM_CAP_SREGS2) > 0;
hv_vpindex_settable = kvm_check_extension(s, KVM_CAP_HYPERV_VP_INDEX);
@@ -2605,11 +2607,11 @@ static int kvm_put_sregs(X86CPU *cpu)
CPUX86State *env = &cpu->env;
struct kvm_sregs sregs;
+ /*
+ * The interrupt_bitmap is ignored because KVM_SET_SREGS is
+ * always followed by KVM_SET_VCPU_EVENTS.
+ */
memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap));
- if (env->interrupt_injected >= 0) {
- sregs.interrupt_bitmap[env->interrupt_injected / 64] |=
- (uint64_t)1 << (env->interrupt_injected % 64);
- }
if ((env->eflags & VM_MASK)) {
set_v8086_seg(&sregs.cs, &env->segs[R_CS]);
@@ -2650,6 +2652,61 @@ static int kvm_put_sregs(X86CPU *cpu)
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs);
}
+static int kvm_put_sregs2(X86CPU *cpu)
+{
+ CPUX86State *env = &cpu->env;
+ struct kvm_sregs2 sregs;
+ int i;
+
+ sregs.flags = 0;
+
+ if ((env->eflags & VM_MASK)) {
+ set_v8086_seg(&sregs.cs, &env->segs[R_CS]);
+ set_v8086_seg(&sregs.ds, &env->segs[R_DS]);
+ set_v8086_seg(&sregs.es, &env->segs[R_ES]);
+ set_v8086_seg(&sregs.fs, &env->segs[R_FS]);
+ set_v8086_seg(&sregs.gs, &env->segs[R_GS]);
+ set_v8086_seg(&sregs.ss, &env->segs[R_SS]);
+ } else {
+ set_seg(&sregs.cs, &env->segs[R_CS]);
+ set_seg(&sregs.ds, &env->segs[R_DS]);
+ set_seg(&sregs.es, &env->segs[R_ES]);
+ set_seg(&sregs.fs, &env->segs[R_FS]);
+ set_seg(&sregs.gs, &env->segs[R_GS]);
+ set_seg(&sregs.ss, &env->segs[R_SS]);
+ }
+
+ set_seg(&sregs.tr, &env->tr);
+ set_seg(&sregs.ldt, &env->ldt);
+
+ sregs.idt.limit = env->idt.limit;
+ sregs.idt.base = env->idt.base;
+ memset(sregs.idt.padding, 0, sizeof sregs.idt.padding);
+ sregs.gdt.limit = env->gdt.limit;
+ sregs.gdt.base = env->gdt.base;
+ memset(sregs.gdt.padding, 0, sizeof sregs.gdt.padding);
+
+ sregs.cr0 = env->cr[0];
+ sregs.cr2 = env->cr[2];
+ sregs.cr3 = env->cr[3];
+ sregs.cr4 = env->cr[4];
+
+ sregs.cr8 = cpu_get_apic_tpr(cpu->apic_state);
+ sregs.apic_base = cpu_get_apic_base(cpu->apic_state);
+
+ sregs.efer = env->efer;
+
+ if (env->pdptrs_valid) {
+ for (i = 0; i < 4; i++) {
+ sregs.pdptrs[i] = env->pdptrs[i];
+ }
+ sregs.flags |= KVM_SREGS2_FLAGS_PDPTRS_VALID;
+ }
+
+ return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS2, &sregs);
+}
+
+
static void kvm_msr_buf_reset(X86CPU *cpu)
{
memset(cpu->kvm_msr_buf, 0, MSR_BUF_SIZE);
@@ -3284,22 +3341,55 @@ static int kvm_get_sregs(X86CPU *cpu)
{
CPUX86State *env = &cpu->env;
struct kvm_sregs sregs;
- int bit, i, ret;
+ int ret;
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs);
if (ret < 0) {
return ret;
}
- /* There can only be one pending IRQ set in the bitmap at a time, so try
- to find it and save its number instead (-1 for none). */
- env->interrupt_injected = -1;
- for (i = 0; i < ARRAY_SIZE(sregs.interrupt_bitmap); i++) {
- if (sregs.interrupt_bitmap[i]) {
- bit = ctz64(sregs.interrupt_bitmap[i]);
- env->interrupt_injected = i * 64 + bit;
- break;
- }
+ /*
+ * The interrupt_bitmap is ignored because KVM_GET_SREGS is
+ * always preceded by KVM_GET_VCPU_EVENTS.
+ */
+
+ get_seg(&env->segs[R_CS], &sregs.cs);
+ get_seg(&env->segs[R_DS], &sregs.ds);
+ get_seg(&env->segs[R_ES], &sregs.es);
+ get_seg(&env->segs[R_FS], &sregs.fs);
+ get_seg(&env->segs[R_GS], &sregs.gs);
+ get_seg(&env->segs[R_SS], &sregs.ss);
+
+ get_seg(&env->tr, &sregs.tr);
+ get_seg(&env->ldt, &sregs.ldt);
+
+ env->idt.limit = sregs.idt.limit;
+ env->idt.base = sregs.idt.base;
+ env->gdt.limit = sregs.gdt.limit;
+ env->gdt.base = sregs.gdt.base;
+
+ env->cr[0] = sregs.cr0;
+ env->cr[2] = sregs.cr2;
+ env->cr[3] = sregs.cr3;
+ env->cr[4] = sregs.cr4;
+
+ env->efer = sregs.efer;
+
+ /* changes to apic base and cr8/tpr are read back via kvm_arch_post_run */
+ x86_update_hflags(env);
+
+ return 0;
+}
+
+static int kvm_get_sregs2(X86CPU *cpu)
+{
+ CPUX86State *env = &cpu->env;
+ struct kvm_sregs2 sregs;
+ int i, ret;
+
+ ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS2, &sregs);
+ if (ret < 0) {
+ return ret;
}
get_seg(&env->segs[R_CS], &sregs.cs);
@@ -3324,6 +3414,14 @@ static int kvm_get_sregs(X86CPU *cpu)
env->efer = sregs.efer;
+ env->pdptrs_valid = sregs.flags & KVM_SREGS2_FLAGS_PDPTRS_VALID;
+
+ if (env->pdptrs_valid) {
+ for (i = 0; i < 4; i++) {
+ env->pdptrs[i] = sregs.pdptrs[i];
+ }
+ }
+
/* changes to apic base and cr8/tpr are read back via kvm_arch_post_run */
x86_update_hflags(env);
@@ -4173,7 +4271,7 @@ int kvm_arch_put_registers(CPUState *cpu, int level)
assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));
/* must be before kvm_put_nested_state so that EFER.SVME is set */
- ret = kvm_put_sregs(x86_cpu);
+ ret = has_sregs2 ? kvm_put_sregs2(x86_cpu) : kvm_put_sregs(x86_cpu);
if (ret < 0) {
return ret;
}
@@ -4278,7 +4376,7 @@ int kvm_arch_get_registers(CPUState *cs)
if (ret < 0) {
goto out;
}
- ret = kvm_get_sregs(cpu);
+ ret = has_sregs2 ? kvm_get_sregs2(cpu) : kvm_get_sregs(cpu);
if (ret < 0) {
goto out;
}
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 83c2b91529..6202f47793 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -1451,6 +1451,34 @@ static const VMStateDescription vmstate_msr_intel_sgx = {
.needed = intel_sgx_msrs_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64_ARRAY(env.msr_ia32_sgxlepubkeyhash, X86CPU, 4),
+ VMSTATE_END_OF_LIST()
+ }
+ };
+
+static bool pdptrs_needed(void *opaque)
+{
+ X86CPU *cpu = opaque;
+ CPUX86State *env = &cpu->env;
+ return env->pdptrs_valid;
+}
+
+static int pdptrs_post_load(void *opaque, int version_id)
+{
+ X86CPU *cpu = opaque;
+ CPUX86State *env = &cpu->env;
+ env->pdptrs_valid = true;
+ return 0;
+}
+
+
+static const VMStateDescription vmstate_pdptrs = {
+ .name = "cpu/pdptrs",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = pdptrs_needed,
+ .post_load = pdptrs_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64_ARRAY(env.pdptrs, X86CPU, 4),
VMSTATE_END_OF_LIST()
}
};
@@ -1593,6 +1621,7 @@ const VMStateDescription vmstate_x86_cpu = {
#endif
&vmstate_msr_tsx_ctrl,
&vmstate_msr_intel_sgx,
+ &vmstate_pdptrs,
NULL
}
};
diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index c0f4825034..acbd473515 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -415,7 +415,10 @@ static void m68k_interrupt_all(CPUM68KState *env, int is_hw)
oldsr = sr;
env->aregs[7] = sp;
cpu_m68k_set_sr(env, sr &= ~SR_M);
- sp = env->aregs[7] & ~1;
+ sp = env->aregs[7];
+ if (!m68k_feature(env, M68K_FEATURE_UNALIGNED_DATA)) {
+ sp &= ~1;
+ }
do_stack_frame(env, &sp, 1, oldsr, 0, retaddr);
} else {
do_stack_frame(env, &sp, 0, oldsr, 0, retaddr);
diff --git a/target/mips/tcg/micromips_translate.c.inc b/target/mips/tcg/micromips_translate.c.inc
index 0760941431..fc6ede75b8 100644
--- a/target/mips/tcg/micromips_translate.c.inc
+++ b/target/mips/tcg/micromips_translate.c.inc
@@ -822,7 +822,7 @@ static void gen_pool16c_insn(DisasContext *ctx)
gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
break;
case BREAK16:
- generate_exception_end(ctx, EXCP_BREAK);
+ generate_exception_break(ctx, extract32(ctx->opcode, 0, 4));
break;
case SDBBP16:
if (is_uhi(extract32(ctx->opcode, 0, 4))) {
@@ -937,7 +937,7 @@ static void gen_pool16c_r6_insn(DisasContext *ctx)
break;
case R6_BREAK16:
/* BREAK16 */
- generate_exception(ctx, EXCP_BREAK);
+ generate_exception_break(ctx, extract32(ctx->opcode, 6, 4));
break;
case R6_SDBBP16:
/* SDBBP16 */
@@ -1047,7 +1047,7 @@ static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
case TNE:
mips32_op = OPC_TNE;
do_trap:
- gen_trap(ctx, mips32_op, rs, rt, -1);
+ gen_trap(ctx, mips32_op, rs, rt, -1, extract32(ctx->opcode, 12, 4));
break;
#ifndef CONFIG_USER_ONLY
case MFC0:
@@ -1812,7 +1812,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
gen_pool32axf(env, ctx, rt, rs);
break;
case BREAK32:
- generate_exception_end(ctx, EXCP_BREAK);
+ generate_exception_break(ctx, extract32(ctx->opcode, 6, 20));
break;
case SIGRIE:
check_insn(ctx, ISA_MIPS_R6);
@@ -2439,7 +2439,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
check_insn_opc_removed(ctx, ISA_MIPS_R6);
mips32_op = OPC_TEQI;
do_trapi:
- gen_trap(ctx, mips32_op, rs, -1, imm);
+ gen_trap(ctx, mips32_op, rs, -1, imm, 0);
break;
case BNEZC:
diff --git a/target/mips/tcg/mips16e_translate.c.inc b/target/mips/tcg/mips16e_translate.c.inc
index 84d816603a..f57e0a5f2a 100644
--- a/target/mips/tcg/mips16e_translate.c.inc
+++ b/target/mips/tcg/mips16e_translate.c.inc
@@ -969,7 +969,7 @@ static int decode_ase_mips16e(CPUMIPSState *env, DisasContext *ctx)
gen_slt(ctx, OPC_SLTU, 24, rx, ry);
break;
case RR_BREAK:
- generate_exception_end(ctx, EXCP_BREAK);
+ generate_exception_break(ctx, extract32(ctx->opcode, 5, 6));
break;
case RR_SLLV:
gen_shift(ctx, OPC_SLLV, ry, rx, ry);
diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc
index 2c022a49f2..916cece4d2 100644
--- a/target/mips/tcg/nanomips_translate.c.inc
+++ b/target/mips/tcg/nanomips_translate.c.inc
@@ -1268,11 +1268,11 @@ static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
switch (extract32(ctx->opcode, 10, 1)) {
case NM_TEQ:
check_nms(ctx);
- gen_trap(ctx, OPC_TEQ, rs, rt, -1);
+ gen_trap(ctx, OPC_TEQ, rs, rt, -1, rd);
break;
case NM_TNE:
check_nms(ctx);
- gen_trap(ctx, OPC_TNE, rs, rt, -1);
+ gen_trap(ctx, OPC_TNE, rs, rt, -1, rd);
break;
}
break;
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 1c2264417c..b82a7ec6ad 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -1367,6 +1367,16 @@ void generate_exception_end(DisasContext *ctx, int excp)
generate_exception_err(ctx, excp, 0);
}
+void generate_exception_break(DisasContext *ctx, int code)
+{
+#ifdef CONFIG_USER_ONLY
+ /* Pass the break code along to cpu_loop. */
+ tcg_gen_st_i32(tcg_constant_i32(code), cpu_env,
+ offsetof(CPUMIPSState, error_code));
+#endif
+ generate_exception_end(ctx, EXCP_BREAK);
+}
+
void gen_reserved_instruction(DisasContext *ctx)
{
generate_exception_end(ctx, EXCP_RI);
@@ -4723,7 +4733,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
/* Traps */
static void gen_trap(DisasContext *ctx, uint32_t opc,
- int rs, int rt, int16_t imm)
+ int rs, int rt, int16_t imm, int code)
{
int cond;
TCGv t0 = tcg_temp_new();
@@ -4768,6 +4778,11 @@ static void gen_trap(DisasContext *ctx, uint32_t opc,
case OPC_TGEU: /* rs >= rs unsigned */
case OPC_TGEIU: /* r0 >= 0 unsigned */
/* Always trap */
+#ifdef CONFIG_USER_ONLY
+ /* Pass the break code along to cpu_loop. */
+ tcg_gen_st_i32(tcg_constant_i32(code), cpu_env,
+ offsetof(CPUMIPSState, error_code));
+#endif
generate_exception_end(ctx, EXCP_TRAP);
break;
case OPC_TLT: /* rs < rs */
@@ -4808,6 +4823,18 @@ static void gen_trap(DisasContext *ctx, uint32_t opc,
tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
break;
}
+#ifdef CONFIG_USER_ONLY
+ /* Pass the break code along to cpu_loop. */
+ tcg_gen_st_i32(tcg_constant_i32(code), cpu_env,
+ offsetof(CPUMIPSState, error_code));
+#endif
+ /* Like save_cpu_state, only don't update saved values. */
+ if (ctx->base.pc_next != ctx->saved_pc) {
+ gen_save_pc(ctx->base.pc_next);
+ }
+ if (ctx->hflags != ctx->saved_hflags) {
+ tcg_gen_movi_i32(hflags, ctx->hflags);
+ }
generate_exception(ctx, EXCP_TRAP);
gen_set_label(l1);
}
@@ -14145,7 +14172,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
case OPC_TEQ:
case OPC_TNE:
check_insn(ctx, ISA_MIPS2);
- gen_trap(ctx, op1, rs, rt, -1);
+ gen_trap(ctx, op1, rs, rt, -1, extract32(ctx->opcode, 6, 10));
break;
case OPC_PMON:
/* Pmon entry point, also R4010 selsl */
@@ -14160,7 +14187,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
generate_exception_end(ctx, EXCP_SYSCALL);
break;
case OPC_BREAK:
- generate_exception_end(ctx, EXCP_BREAK);
+ generate_exception_break(ctx, extract32(ctx->opcode, 6, 20));
break;
case OPC_SYNC:
check_insn(ctx, ISA_MIPS2);
@@ -15279,11 +15306,10 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
case OPC_TLTI:
case OPC_TLTIU:
case OPC_TEQI:
-
case OPC_TNEI:
check_insn(ctx, ISA_MIPS2);
check_insn_opc_removed(ctx, ISA_MIPS_R6);
- gen_trap(ctx, op1, rs, -1, imm);
+ gen_trap(ctx, op1, rs, -1, imm, 0);
break;
case OPC_SIGRIE:
check_insn(ctx, ISA_MIPS_R6);
diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h
index 6111493651..ae01515efe 100644
--- a/target/mips/tcg/translate.h
+++ b/target/mips/tcg/translate.h
@@ -129,6 +129,7 @@ enum {
void generate_exception(DisasContext *ctx, int excp);
void generate_exception_err(DisasContext *ctx, int excp, int err);
void generate_exception_end(DisasContext *ctx, int excp);
+void generate_exception_break(DisasContext *ctx, int code);
void gen_reserved_instruction(DisasContext *ctx);
void check_insn(DisasContext *ctx, uint64_t flags);
diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c
index bb392f6d88..993740897d 100644
--- a/target/ppc/arch_dump.c
+++ b/target/ppc/arch_dump.c
@@ -237,7 +237,7 @@ int cpu_get_dump_info(ArchDumpInfo *info,
info->d_machine = PPC_ELF_MACHINE;
info->d_class = ELFCLASS;
- if (ppc_interrupts_little_endian(cpu)) {
+ if (ppc_interrupts_little_endian(cpu, cpu->env.has_hv_mode)) {
info->d_endian = ELFDATA2LSB;
} else {
info->d_endian = ELFDATA2MSB;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index f20d4ffa6d..f99cd0ea92 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -2728,20 +2728,29 @@ static inline bool ppc_has_spr(PowerPCCPU *cpu, int spr)
return cpu->env.spr_cb[spr].name != NULL;
}
-static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu)
+#if !defined(CONFIG_USER_ONLY)
+static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu, bool hv)
{
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ CPUPPCState *env = &cpu->env;
+ bool ile;
+
+ if (hv && env->has_hv_mode) {
+ if (is_isa300(pcc)) {
+ ile = !!(env->spr[SPR_HID0] & HID0_POWER9_HILE);
+ } else {
+ ile = !!(env->spr[SPR_HID0] & HID0_HILE);
+ }
- /*
- * Only models that have an LPCR and know about LPCR_ILE can do little
- * endian.
- */
- if (pcc->lpcr_mask & LPCR_ILE) {
- return !!(cpu->env.spr[SPR_LPCR] & LPCR_ILE);
+ } else if (pcc->lpcr_mask & LPCR_ILE) {
+ ile = !!(env->spr[SPR_LPCR] & LPCR_ILE);
+ } else {
+ ile = !!(msr_ile);
}
- return false;
+ return ile;
}
+#endif
void dump_mmu(CPUPPCState *env);
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index cc93bff3fa..e30e86fe9d 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -6953,10 +6953,12 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
PPC_FLOAT_STFIWX |
+ PPC_FLOAT_EXT |
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_64B |
+ PPC_POPCNTB |
PPC_SEGMENT_64B | PPC_SLBI;
pcc->insns_flags2 = PPC2_FP_CVT_S64;
pcc->msr_mask = (1ull << MSR_SF) |
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index a779dc936a..bc646c67a0 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -30,8 +30,6 @@
#include "exec/cpu_ldst.h"
#endif
-/* #define DEBUG_SOFTWARE_TLB */
-
/*****************************************************************************/
/* Exception processing */
#if !defined(CONFIG_USER_ONLY)
@@ -135,6 +133,39 @@ static void dump_hcall(CPUPPCState *env)
env->nip);
}
+static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp)
+{
+ const char *es;
+ target_ulong *miss, *cmp;
+ int en;
+
+ if (!qemu_loglevel_mask(CPU_LOG_MMU)) {
+ return;
+ }
+
+ if (excp == POWERPC_EXCP_IFTLB) {
+ es = "I";
+ en = 'I';
+ miss = &env->spr[SPR_IMISS];
+ cmp = &env->spr[SPR_ICMP];
+ } else {
+ if (excp == POWERPC_EXCP_DLTLB) {
+ es = "DL";
+ } else {
+ es = "DS";
+ }
+ en = 'D';
+ miss = &env->spr[SPR_DMISS];
+ cmp = &env->spr[SPR_DCMP];
+ }
+ qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
+ TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
+ TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
+ env->spr[SPR_HASH1], env->spr[SPR_HASH2],
+ env->error_code);
+}
+
+
static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
target_ulong *msr)
{
@@ -365,7 +396,7 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu,
* Note that this function should be greatly optimized when called
* with a constant excp, from ppc_hw_interrupt
*/
-static void powerpc_excp(PowerPCCPU *cpu, int excp)
+static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
@@ -669,23 +700,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */
env->spr[SPR_BOOKE_ESR] = ESR_SPV;
break;
- case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
- /* XXX: TODO */
- cpu_abort(cs, "Embedded floating point data exception "
- "is not implemented yet !\n");
- env->spr[SPR_BOOKE_ESR] = ESR_SPV;
- break;
- case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
- /* XXX: TODO */
- cpu_abort(cs, "Embedded floating point round exception "
- "is not implemented yet !\n");
- env->spr[SPR_BOOKE_ESR] = ESR_SPV;
- break;
- case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
- /* XXX: TODO */
- cpu_abort(cs,
- "Performance counter exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
break;
case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
@@ -750,19 +764,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
trace_ppc_excp_print("PIT");
break;
- case POWERPC_EXCP_IO: /* IO error exception */
- /* XXX: TODO */
- cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
- break;
- case POWERPC_EXCP_RUNM: /* Run mode exception */
- /* XXX: TODO */
- cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
- break;
- case POWERPC_EXCP_EMUL: /* Emulation trap exception */
- /* XXX: TODO */
- cpu_abort(cs, "602 emulation trap exception "
- "is not implemented yet !\n");
- break;
case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
@@ -777,34 +778,8 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
}
/* fall through */
case POWERPC_EXCP_7x5:
-#if defined(DEBUG_SOFTWARE_TLB)
- if (qemu_log_enabled()) {
- const char *es;
- target_ulong *miss, *cmp;
- int en;
-
- if (excp == POWERPC_EXCP_IFTLB) {
- es = "I";
- en = 'I';
- miss = &env->spr[SPR_IMISS];
- cmp = &env->spr[SPR_ICMP];
- } else {
- if (excp == POWERPC_EXCP_DLTLB) {
- es = "DL";
- } else {
- es = "DS";
- }
- en = 'D';
- miss = &env->spr[SPR_DMISS];
- cmp = &env->spr[SPR_DCMP];
- }
- qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
- TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
- TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
- env->spr[SPR_HASH1], env->spr[SPR_HASH2],
- env->error_code);
- }
-#endif
+ ppc_excp_debug_sw_tlb(env, excp);
+
msr |= env->crf[0] << 28;
msr |= env->error_code; /* key, D/I, S/L bits */
/* Set way using a LRU mechanism */
@@ -815,56 +790,25 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
break;
}
break;
+ case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
+ case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
+ case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
+ case POWERPC_EXCP_IO: /* IO error exception */
+ case POWERPC_EXCP_RUNM: /* Run mode exception */
+ case POWERPC_EXCP_EMUL: /* Emulation trap exception */
case POWERPC_EXCP_FPA: /* Floating-point assist exception */
- /* XXX: TODO */
- cpu_abort(cs, "Floating point assist exception "
- "is not implemented yet !\n");
- break;
case POWERPC_EXCP_DABR: /* Data address breakpoint */
- /* XXX: TODO */
- cpu_abort(cs, "DABR exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
- /* XXX: TODO */
- cpu_abort(cs, "IABR exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_SMI: /* System management interrupt */
- /* XXX: TODO */
- cpu_abort(cs, "SMI exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_THERM: /* Thermal interrupt */
- /* XXX: TODO */
- cpu_abort(cs, "Thermal management exception "
- "is not implemented yet !\n");
- break;
case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
- /* XXX: TODO */
- cpu_abort(cs,
- "Performance counter exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_VPUA: /* Vector assist exception */
- /* XXX: TODO */
- cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_SOFTP: /* Soft patch exception */
- /* XXX: TODO */
- cpu_abort(cs,
- "970 soft-patch exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_MAINT: /* Maintenance exception */
- /* XXX: TODO */
- cpu_abort(cs,
- "970 maintenance exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
- /* XXX: TODO */
- cpu_abort(cs, "Maskable external exception "
- "is not implemented yet !\n");
- break;
case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
- /* XXX: TODO */
- cpu_abort(cs, "Non maskable external exception "
- "is not implemented yet !\n");
+ cpu_abort(cs, "%s exception not implemented\n",
+ powerpc_excp_name(excp));
break;
default:
excp_invalid:
@@ -888,36 +832,9 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
* Sort out endianness of interrupt, this differs depending on the
* CPU, the HV mode, etc...
*/
-#ifdef TARGET_PPC64
- if (excp_model == POWERPC_EXCP_POWER7) {
- if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) {
- new_msr |= (target_ulong)1 << MSR_LE;
- }
- } else if (excp_model == POWERPC_EXCP_POWER8) {
- if (new_msr & MSR_HVB) {
- if (env->spr[SPR_HID0] & HID0_HILE) {
- new_msr |= (target_ulong)1 << MSR_LE;
- }
- } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
- new_msr |= (target_ulong)1 << MSR_LE;
- }
- } else if (excp_model == POWERPC_EXCP_POWER9 ||
- excp_model == POWERPC_EXCP_POWER10) {
- if (new_msr & MSR_HVB) {
- if (env->spr[SPR_HID0] & HID0_POWER9_HILE) {
- new_msr |= (target_ulong)1 << MSR_LE;
- }
- } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
- new_msr |= (target_ulong)1 << MSR_LE;
- }
- } else if (msr_ile) {
+ if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
new_msr |= (target_ulong)1 << MSR_LE;
}
-#else
- if (msr_ile) {
- new_msr |= (target_ulong)1 << MSR_LE;
- }
-#endif
#if defined(TARGET_PPC64)
if (excp_model == POWERPC_EXCP_BOOKE) {
@@ -950,6 +867,16 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
powerpc_set_excp_state(cpu, vector, new_msr);
}
+static void powerpc_excp(PowerPCCPU *cpu, int excp)
+{
+ CPUPPCState *env = &cpu->env;
+
+ switch (env->excp_model) {
+ default:
+ powerpc_excp_legacy(cpu, excp);
+ }
+}
+
void ppc_cpu_do_interrupt(CPUState *cs)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -1126,7 +1053,7 @@ void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
*/
msr = (1ULL << MSR_ME);
msr |= env->msr & (1ULL << MSR_SF);
- if (ppc_interrupts_little_endian(cpu)) {
+ if (ppc_interrupts_little_endian(cpu, false)) {
msr |= (1ULL << MSR_LE);
}
diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
index efb260d822..be0f6b79e5 100755
--- a/tests/qemu-iotests/122
+++ b/tests/qemu-iotests/122
@@ -251,6 +251,7 @@ $QEMU_IO -c "write -P 0 0 64k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_test
$QEMU_IO -c "write 0 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
$QEMU_IO -c "write 8k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
$QEMU_IO -c "write 17k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
+$QEMU_IO -c "write -P 0 65k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
for min_sparse in 4k 8k; do
echo
diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
index 8fbdac2b39..e18766e167 100644
--- a/tests/qemu-iotests/122.out
+++ b/tests/qemu-iotests/122.out
@@ -192,6 +192,8 @@ wrote 1024/1024 bytes at offset 8192
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 1024/1024 bytes at offset 17408
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 66560
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
convert -S 4k
[{ "start": 0, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out
index 4e840b6730..6a74a8138b 100644
--- a/tests/qemu-iotests/273.out
+++ b/tests/qemu-iotests/273.out
@@ -204,7 +204,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"name": "file",
"parent": 5,
"shared-perm": [
- "graph-mod",
"write-unchanged",
"consistent-read"
],
@@ -219,7 +218,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"name": "backing",
"parent": 5,
"shared-perm": [
- "graph-mod",
"resize",
"write-unchanged",
"write",
@@ -233,7 +231,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"name": "file",
"parent": 3,
"shared-perm": [
- "graph-mod",
"write-unchanged",
"consistent-read"
],
@@ -246,7 +243,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"name": "backing",
"parent": 3,
"shared-perm": [
- "graph-mod",
"resize",
"write-unchanged",
"write",
diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308
index 2e3f8f4282..bde4aac2fa 100755
--- a/tests/qemu-iotests/308
+++ b/tests/qemu-iotests/308
@@ -230,8 +230,29 @@ echo '=== Writable export ==='
fuse_export_add 'export-mp' "'mountpoint': '$EXT_MP', 'writable': true"
# Check that writing to the read-only export fails
-$QEMU_IO -f raw -c 'write -P 42 1M 64k' "$TEST_IMG" 2>&1 \
- | _filter_qemu_io | _filter_testdir | _filter_imgfmt
+output=$($QEMU_IO -f raw -c 'write -P 42 1M 64k' "$TEST_IMG" 2>&1 \
+ | _filter_qemu_io | _filter_testdir | _filter_imgfmt)
+
+# Expected reference output: Opening the file fails because it has no
+# write permission
+reference="Could not open 'TEST_DIR/t.IMGFMT': Permission denied"
+
+if echo "$output" | grep -q "$reference"; then
+ echo "Writing to read-only export failed: OK"
+elif echo "$output" | grep -q "write failed: Permission denied"; then
+ # With CAP_DAC_OVERRIDE (e.g. when running this test as root), the export
+ # can be opened regardless of its file permissions, but writing will then
+ # fail. This is not the result for which we want to test, so count this as
+ # a SKIP.
+ _casenotrun "Opening RO export as R/W succeeded, perhaps because of" \
+ "CAP_DAC_OVERRIDE"
+
+ # Still, write this to the reference output to make the test pass
+ echo "Writing to read-only export failed: OK"
+else
+ echo "Writing to read-only export failed: ERROR"
+ echo "$output"
+fi
# But here it should work
$QEMU_IO -f raw -c 'write -P 42 1M 64k' "$EXT_MP" | _filter_qemu_io
diff --git a/tests/qemu-iotests/308.out b/tests/qemu-iotests/308.out
index fc47bb11a2..e4467a10cf 100644
--- a/tests/qemu-iotests/308.out
+++ b/tests/qemu-iotests/308.out
@@ -95,7 +95,7 @@ virtual size: 0 B (0 bytes)
'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true
} }
{"return": {}}
-qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
+Writing to read-only export failed: OK
wrote 65536/65536 bytes at offset 1048576
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 1048576
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
index 0feaa396d0..15788f919e 100644
--- a/tests/qemu-iotests/testrunner.py
+++ b/tests/qemu-iotests/testrunner.py
@@ -174,19 +174,17 @@ class TestRunner(ContextManager['TestRunner']):
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
self._stack.close()
- def test_print_one_line(self, test: str, starttime: str,
+ def test_print_one_line(self, test: str,
+ test_field_width: int,
+ starttime: str,
endtime: Optional[str] = None, status: str = '...',
lasttime: Optional[float] = None,
thistime: Optional[float] = None,
description: str = '',
- test_field_width: Optional[int] = None,
end: str = '\n') -> None:
""" Print short test info before/after test run """
test = os.path.basename(test)
- if test_field_width is None:
- test_field_width = 8
-
if self.makecheck and status != '...':
if status and status != 'pass':
status = f' [{status}]'
@@ -328,7 +326,7 @@ class TestRunner(ContextManager['TestRunner']):
casenotrun=casenotrun)
def run_test(self, test: str,
- test_field_width: Optional[int] = None,
+ test_field_width: int,
mp: bool = False) -> TestResult:
"""
Run one test and print short status
@@ -347,20 +345,21 @@ class TestRunner(ContextManager['TestRunner']):
if not self.makecheck:
self.test_print_one_line(test=test,
+ test_field_width=test_field_width,
status = 'started' if mp else '...',
starttime=start,
lasttime=last_el,
- end = '\n' if mp else '\r',
- test_field_width=test_field_width)
+ end = '\n' if mp else '\r')
res = self.do_run_test(test, mp)
end = datetime.datetime.now().strftime('%H:%M:%S')
- self.test_print_one_line(test=test, status=res.status,
+ self.test_print_one_line(test=test,
+ test_field_width=test_field_width,
+ status=res.status,
starttime=start, endtime=end,
lasttime=last_el, thistime=res.elapsed,
- description=res.description,
- test_field_width=test_field_width)
+ description=res.description)
if res.casenotrun:
print(res.casenotrun)
diff --git a/tests/qemu-iotests/tests/stream-error-on-reset b/tests/qemu-iotests/tests/stream-error-on-reset
new file mode 100755
index 0000000000..7eaedb24d7
--- /dev/null
+++ b/tests/qemu-iotests/tests/stream-error-on-reset
@@ -0,0 +1,140 @@
+#!/usr/bin/env python3
+# group: rw quick
+#
+# Test what happens when a stream job completes in a blk_drain().
+#
+# Copyright (C) 2022 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import iotests
+from iotests import imgfmt, qemu_img_create, qemu_io_silent, QMPTestCase
+
+
+image_size = 1 * 1024 * 1024
+data_size = 64 * 1024
+base = os.path.join(iotests.test_dir, 'base.img')
+top = os.path.join(iotests.test_dir, 'top.img')
+
+
+# We want to test completing a stream job in a blk_drain().
+#
+# The blk_drain() we are going to use is a virtio-scsi device resetting,
+# which we can trigger by resetting the system.
+#
+# In order to have the block job complete on drain, we (1) throttle its
+# base image so we can start the drain after it has begun, but before it
+# completes, and (2) make it encounter an I/O error on the ensuing write.
+# (If it completes regularly, the completion happens after the drain for
+# some reason.)
+
+class TestStreamErrorOnReset(QMPTestCase):
+ def setUp(self) -> None:
+ """
+ Create two images:
+ - base image {base} with {data_size} bytes allocated
+ - top image {top} without any data allocated
+
+ And the following VM configuration:
+ - base image throttled to {data_size}
+ - top image with a blkdebug configuration so the first write access
+ to it will result in an error
+ - top image is attached to a virtio-scsi device
+ """
+ assert qemu_img_create('-f', imgfmt, base, str(image_size)) == 0
+ assert qemu_io_silent('-c', f'write 0 {data_size}', base) == 0
+ assert qemu_img_create('-f', imgfmt, top, str(image_size)) == 0
+
+ self.vm = iotests.VM()
+ self.vm.add_args('-accel', 'tcg') # Make throttling work properly
+ self.vm.add_object(self.vm.qmp_to_opts({
+ 'qom-type': 'throttle-group',
+ 'id': 'thrgr',
+ 'x-bps-total': str(data_size)
+ }))
+ self.vm.add_blockdev(self.vm.qmp_to_opts({
+ 'driver': imgfmt,
+ 'node-name': 'base',
+ 'file': {
+ 'driver': 'throttle',
+ 'throttle-group': 'thrgr',
+ 'file': {
+ 'driver': 'file',
+ 'filename': base
+ }
+ }
+ }))
+ self.vm.add_blockdev(self.vm.qmp_to_opts({
+ 'driver': imgfmt,
+ 'node-name': 'top',
+ 'file': {
+ 'driver': 'blkdebug',
+ 'node-name': 'top-blkdebug',
+ 'inject-error': [{
+ 'event': 'pwritev',
+ 'immediately': 'true',
+ 'once': 'true'
+ }],
+ 'image': {
+ 'driver': 'file',
+ 'filename': top
+ }
+ },
+ 'backing': 'base'
+ }))
+ self.vm.add_device(self.vm.qmp_to_opts({
+ 'driver': 'virtio-scsi',
+ 'id': 'vscsi'
+ }))
+ self.vm.add_device(self.vm.qmp_to_opts({
+ 'driver': 'scsi-hd',
+ 'bus': 'vscsi.0',
+ 'drive': 'top'
+ }))
+ self.vm.launch()
+
+ def tearDown(self) -> None:
+ self.vm.shutdown()
+ os.remove(top)
+ os.remove(base)
+
+ def test_stream_error_on_reset(self) -> None:
+ # Launch a stream job, which will take at least a second to
+ # complete, because the base image is throttled (so we can
+ # get in between it having started and it having completed)
+ res = self.vm.qmp('block-stream', job_id='stream', device='top')
+ self.assert_qmp(res, 'return', {})
+
+ while True:
+ ev = self.vm.event_wait('JOB_STATUS_CHANGE')
+ if ev['data']['status'] == 'running':
+ # Once the stream job is running, reset the system, which
+ # forces the virtio-scsi device to be reset, thus draining
+ # the stream job, and making it complete. Completing
+ # inside of that drain should not result in a segfault.
+ res = self.vm.qmp('system_reset')
+ self.assert_qmp(res, 'return', {})
+ elif ev['data']['status'] == 'null':
+ # The test is done once the job is gone
+ break
+
+
+if __name__ == '__main__':
+ # Passes with any format with backing file support, but qed and
+ # qcow1 do not seem to exercise the used-to-be problematic code
+ # path, so there is no point in having them in this list
+ iotests.main(supported_fmts=['qcow2', 'vmdk'],
+ supported_protocols=['file'])
diff --git a/tests/qemu-iotests/tests/stream-error-on-reset.out b/tests/qemu-iotests/tests/stream-error-on-reset.out
new file mode 100644
index 0000000000..ae1213e6f8
--- /dev/null
+++ b/tests/qemu-iotests/tests/stream-error-on-reset.out
@@ -0,0 +1,5 @@
+.
+----------------------------------------------------------------------
+Ran 1 tests
+
+OK
diff --git a/tests/qtest/device-plug-test.c b/tests/qtest/device-plug-test.c
index 559d47727a..ad79bd4c14 100644
--- a/tests/qtest/device-plug-test.c
+++ b/tests/qtest/device-plug-test.c
@@ -77,6 +77,23 @@ static void test_pci_unplug_request(void)
qtest_quit(qtest);
}
+static void test_pci_unplug_json_request(void)
+{
+ QTestState *qtest = qtest_initf(
+ "-device '{\"driver\": \"virtio-mouse-pci\", \"id\": \"dev0\"}'");
+
+ /*
+ * Request device removal. As the guest is not running, the request won't
+ * be processed. However during system reset, the removal will be
+ * handled, removing the device.
+ */
+ device_del(qtest, "dev0");
+ system_reset(qtest);
+ wait_device_deleted_event(qtest, "dev0");
+
+ qtest_quit(qtest);
+}
+
static void test_ccw_unplug(void)
{
QTestState *qtest = qtest_initf("-device virtio-balloon-ccw,id=dev0");
@@ -145,6 +162,8 @@ int main(int argc, char **argv)
*/
qtest_add_func("/device-plug/pci-unplug-request",
test_pci_unplug_request);
+ qtest_add_func("/device-plug/pci-unplug-json-request",
+ test_pci_unplug_json_request);
if (!strcmp(arch, "s390x")) {
qtest_add_func("/device-plug/ccw-unplug",
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 37e1eaa449..26937deb6d 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -335,10 +335,9 @@ foreach dir : target_dirs
test: executable(test, src, dependencies: deps)
}
endif
- # FIXME: missing dependency on the emulator binary and qemu-img
test('qtest-@0@/@1@'.format(target_base, test),
qtest_executables[test],
- depends: [test_deps, qtest_emulator],
+ depends: [test_deps, qtest_emulator, emulator_modules],
env: qtest_env,
args: ['--tap', '-k'],
protocol: 'tap',
diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target
index 0f8645f782..ae8004c76e 100644
--- a/tests/tcg/Makefile.target
+++ b/tests/tcg/Makefile.target
@@ -33,7 +33,7 @@ all:
-include ../../../config-host.mak
-include ../config-$(TARGET).mak
ifeq ($(CONFIG_USER_ONLY),y)
--include $(SRC_PATH)/default-configs/targets/$(TARGET).mak
+-include $(SRC_PATH)/configs/targets/$(TARGET)/default.mak
endif
# for including , in command strings
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index 90acf5b0da..64a5e7bfde 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -129,7 +129,7 @@ if have_system
'test-vmstate': [migration, io],
'test-yank': ['socket-helpers.c', qom, io, chardev]
}
- if 'CONFIG_INOTIFY1' in config_host
+ if config_host_data.get('CONFIG_INOTIFY1')
tests += {'test-util-filemonitor': []}
endif
diff --git a/tests/unit/test-aio.c b/tests/unit/test-aio.c
index 6feeb9a4a9..178048d2f2 100644
--- a/tests/unit/test-aio.c
+++ b/tests/unit/test-aio.c
@@ -130,7 +130,7 @@ static void *test_acquire_thread(void *opaque)
static void set_event_notifier(AioContext *ctx, EventNotifier *notifier,
EventNotifierHandler *handler)
{
- aio_set_event_notifier(ctx, notifier, false, handler, NULL);
+ aio_set_event_notifier(ctx, notifier, false, handler, NULL, NULL);
}
static void dummy_notifier_read(EventNotifier *n)
@@ -390,7 +390,7 @@ static void test_aio_external_client(void)
for (i = 1; i < 3; i++) {
EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, true, event_ready_cb, NULL);
+ aio_set_event_notifier(ctx, &data.e, true, event_ready_cb, NULL, NULL);
event_notifier_set(&data.e);
for (j = 0; j < i; j++) {
aio_disable_external(ctx);
diff --git a/tests/unit/test-fdmon-epoll.c b/tests/unit/test-fdmon-epoll.c
index 11fd8a2fa9..ef5a856d09 100644
--- a/tests/unit/test-fdmon-epoll.c
+++ b/tests/unit/test-fdmon-epoll.c
@@ -22,14 +22,14 @@ static void add_event_notifiers(EventNotifier *notifiers, size_t n)
for (size_t i = 0; i < n; i++) {
event_notifier_init(&notifiers[i], false);
aio_set_event_notifier(ctx, &notifiers[i], false,
- dummy_fd_handler, NULL);
+ dummy_fd_handler, NULL, NULL);
}
}
static void remove_event_notifiers(EventNotifier *notifiers, size_t n)
{
for (size_t i = 0; i < n; i++) {
- aio_set_event_notifier(ctx, &notifiers[i], false, NULL, NULL);
+ aio_set_event_notifier(ctx, &notifiers[i], false, NULL, NULL, NULL);
event_notifier_cleanup(&notifiers[i]);
}
}
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 69745c483b..ac18e14ce0 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -970,21 +970,27 @@ QemuCocoaView *cocoaView;
*/
/*
- * When deltaY is zero, it means that this scrolling event was
- * either horizontal, or so fine that it only appears in
- * scrollingDeltaY. So we drop the event.
+ * We shouldn't have got a scroll event when deltaY and delta Y
+ * are zero, hence no harm in dropping the event
*/
- if ([event deltaY] != 0) {
+ if ([event deltaY] != 0 || [event deltaX] != 0) {
/* Determine if this is a scroll up or scroll down event */
- buttons = ([event deltaY] > 0) ?
+ if ([event deltaY] != 0) {
+ buttons = ([event deltaY] > 0) ?
INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHEEL_DOWN;
+ } else if ([event deltaX] != 0) {
+ buttons = ([event deltaX] > 0) ?
+ INPUT_BUTTON_WHEEL_LEFT : INPUT_BUTTON_WHEEL_RIGHT;
+ }
+
qemu_input_queue_btn(dcl.con, buttons, true);
qemu_input_event_sync();
qemu_input_queue_btn(dcl.con, buttons, false);
qemu_input_event_sync();
}
+
/*
- * Since deltaY also reports scroll wheel events we prevent mouse
+ * Since deltaX/deltaY also report scroll wheel events we prevent mouse
* movement code from executing.
*/
mouse_event = false;
diff --git a/ui/dbus.c b/ui/dbus.c
index b2c1c9fb52..0074424c1f 100644
--- a/ui/dbus.c
+++ b/ui/dbus.c
@@ -405,6 +405,7 @@ dbus_vc_class_init(ObjectClass *oc, void *data)
static const TypeInfo dbus_vc_type_info = {
.name = TYPE_CHARDEV_VC,
.parent = TYPE_CHARDEV_DBUS,
+ .class_size = sizeof(DBusVCClass),
.class_init = dbus_vc_class_init,
};
diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c
index e0b8b283fe..d58fd761ab 100644
--- a/ui/gtk-clipboard.c
+++ b/ui/gtk-clipboard.c
@@ -83,7 +83,7 @@ static void gd_clipboard_update_info(GtkDisplayState *gd,
if (info != qemu_clipboard_info(s)) {
gd->cbpending[s] = 0;
if (!self_update) {
- GtkTargetList *list;
+ g_autoptr(GtkTargetList) list = NULL;
GtkTargetEntry *targets;
gint n_targets;
@@ -94,15 +94,16 @@ static void gd_clipboard_update_info(GtkDisplayState *gd,
targets = gtk_target_table_new_from_list(list, &n_targets);
gtk_clipboard_clear(gd->gtkcb[s]);
- gd->cbowner[s] = true;
- gtk_clipboard_set_with_data(gd->gtkcb[s],
- targets, n_targets,
- gd_clipboard_get_data,
- gd_clipboard_clear,
- gd);
-
- gtk_target_table_free(targets, n_targets);
- gtk_target_list_unref(list);
+ if (targets) {
+ gd->cbowner[s] = true;
+ gtk_clipboard_set_with_data(gd->gtkcb[s],
+ targets, n_targets,
+ gd_clipboard_get_data,
+ gd_clipboard_clear,
+ gd);
+
+ gtk_target_table_free(targets, n_targets);
+ }
}
return;
}
diff --git a/ui/gtk.c b/ui/gtk.c
index 6a1f65d518..a8567b9ddc 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -968,33 +968,63 @@ static gboolean gd_scroll_event(GtkWidget *widget, GdkEventScroll *scroll,
void *opaque)
{
VirtualConsole *vc = opaque;
- InputButton btn;
+ InputButton btn_vertical;
+ InputButton btn_horizontal;
+ bool has_vertical = false;
+ bool has_horizontal = false;
if (scroll->direction == GDK_SCROLL_UP) {
- btn = INPUT_BUTTON_WHEEL_UP;
+ btn_vertical = INPUT_BUTTON_WHEEL_UP;
+ has_vertical = true;
} else if (scroll->direction == GDK_SCROLL_DOWN) {
- btn = INPUT_BUTTON_WHEEL_DOWN;
+ btn_vertical = INPUT_BUTTON_WHEEL_DOWN;
+ has_vertical = true;
+ } else if (scroll->direction == GDK_SCROLL_LEFT) {
+ btn_horizontal = INPUT_BUTTON_WHEEL_LEFT;
+ has_horizontal = true;
+ } else if (scroll->direction == GDK_SCROLL_RIGHT) {
+ btn_horizontal = INPUT_BUTTON_WHEEL_RIGHT;
+ has_horizontal = true;
} else if (scroll->direction == GDK_SCROLL_SMOOTH) {
gdouble delta_x, delta_y;
if (!gdk_event_get_scroll_deltas((GdkEvent *)scroll,
&delta_x, &delta_y)) {
return TRUE;
}
- if (delta_y == 0) {
- return TRUE;
- } else if (delta_y > 0) {
- btn = INPUT_BUTTON_WHEEL_DOWN;
+
+ if (delta_y > 0) {
+ btn_vertical = INPUT_BUTTON_WHEEL_DOWN;
+ has_vertical = true;
+ } else if (delta_y < 0) {
+ btn_vertical = INPUT_BUTTON_WHEEL_UP;
+ has_vertical = true;
+ } else if (delta_x > 0) {
+ btn_horizontal = INPUT_BUTTON_WHEEL_RIGHT;
+ has_horizontal = true;
+ } else if (delta_x < 0) {
+ btn_horizontal = INPUT_BUTTON_WHEEL_LEFT;
+ has_horizontal = true;
} else {
- btn = INPUT_BUTTON_WHEEL_UP;
+ return TRUE;
}
} else {
return TRUE;
}
- qemu_input_queue_btn(vc->gfx.dcl.con, btn, true);
- qemu_input_event_sync();
- qemu_input_queue_btn(vc->gfx.dcl.con, btn, false);
- qemu_input_event_sync();
+ if (has_vertical) {
+ qemu_input_queue_btn(vc->gfx.dcl.con, btn_vertical, true);
+ qemu_input_event_sync();
+ qemu_input_queue_btn(vc->gfx.dcl.con, btn_vertical, false);
+ qemu_input_event_sync();
+ }
+
+ if (has_horizontal) {
+ qemu_input_queue_btn(vc->gfx.dcl.con, btn_horizontal, true);
+ qemu_input_event_sync();
+ qemu_input_queue_btn(vc->gfx.dcl.con, btn_horizontal, false);
+ qemu_input_event_sync();
+ }
+
return TRUE;
}
diff --git a/ui/input-legacy.c b/ui/input-legacy.c
index 9fc78a639b..46ea74e44d 100644
--- a/ui/input-legacy.c
+++ b/ui/input-legacy.c
@@ -23,6 +23,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/log.h"
#include "qapi/qapi-commands-ui.h"
#include "ui/console.h"
#include "keymaps.h"
@@ -179,6 +180,20 @@ static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
1,
s->buttons);
}
+ if (btn->down && btn->button == INPUT_BUTTON_WHEEL_RIGHT) {
+ s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
+ s->axis[INPUT_AXIS_X],
+ s->axis[INPUT_AXIS_Y],
+ -2,
+ s->buttons);
+ }
+ if (btn->down && btn->button == INPUT_BUTTON_WHEEL_LEFT) {
+ s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
+ s->axis[INPUT_AXIS_X],
+ s->axis[INPUT_AXIS_Y],
+ 2,
+ s->buttons);
+ }
break;
case INPUT_EVENT_KIND_ABS:
move = evt->u.abs.data;
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 0bd30504cf..46a252d7d9 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -33,6 +33,7 @@
#include "sysemu/runstate-action.h"
#include "sysemu/sysemu.h"
#include "ui/win32-kbd-hook.h"
+#include "qemu/log.h"
static int sdl2_num_outputs;
static struct sdl2_console *sdl2_console;
@@ -535,6 +536,10 @@ static void handle_mousewheel(SDL_Event *ev)
btn = INPUT_BUTTON_WHEEL_UP;
} else if (wev->y < 0) {
btn = INPUT_BUTTON_WHEEL_DOWN;
+ } else if (wev->x < 0) {
+ btn = INPUT_BUTTON_WHEEL_RIGHT;
+ } else if (wev->x > 0) {
+ btn = INPUT_BUTTON_WHEEL_LEFT;
} else {
return;
}
diff --git a/ui/vnc.c b/ui/vnc.c
index 1ed1c7efc6..3ccd33dedc 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1354,12 +1354,12 @@ void vnc_disconnect_finish(VncState *vs)
/* last client gone */
vnc_update_server_surface(vs->vd);
}
+ vnc_unlock_output(vs);
+
if (vs->cbpeer.notifier.notify) {
qemu_clipboard_peer_unregister(&vs->cbpeer);
}
- vnc_unlock_output(vs);
-
qemu_mutex_destroy(&vs->output_mutex);
if (vs->bh != NULL) {
qemu_bh_delete(vs->bh);
diff --git a/util/aio-posix.c b/util/aio-posix.c
index 2b86777e91..7b9f629218 100644
--- a/util/aio-posix.c
+++ b/util/aio-posix.c
@@ -23,6 +23,15 @@
#include "trace.h"
#include "aio-posix.h"
+/*
+ * G_IO_IN and G_IO_OUT are not appropriate revents values for polling, since
+ * the handler may not need to access the file descriptor. For example, the
+ * handler doesn't need to read from an EventNotifier if it polled a memory
+ * location and a read syscall would be slow. Define our own unique revents
+ * value to indicate that polling determined this AioHandler is ready.
+ */
+#define REVENTS_POLL_READY 0
+
/* Stop userspace polling on a handler if it isn't active for some time */
#define POLL_IDLE_INTERVAL_NS (7 * NANOSECONDS_PER_SECOND)
@@ -93,6 +102,7 @@ void aio_set_fd_handler(AioContext *ctx,
IOHandler *io_read,
IOHandler *io_write,
AioPollFn *io_poll,
+ IOHandler *io_poll_ready,
void *opaque)
{
AioHandler *node;
@@ -101,6 +111,10 @@ void aio_set_fd_handler(AioContext *ctx,
bool deleted = false;
int poll_disable_change;
+ if (io_poll && !io_poll_ready) {
+ io_poll = NULL; /* polling only makes sense if there is a handler */
+ }
+
qemu_lockcnt_lock(&ctx->list_lock);
node = find_aio_handler(ctx, fd);
@@ -127,6 +141,7 @@ void aio_set_fd_handler(AioContext *ctx,
new_node->io_read = io_read;
new_node->io_write = io_write;
new_node->io_poll = io_poll;
+ new_node->io_poll_ready = io_poll_ready;
new_node->opaque = opaque;
new_node->is_external = is_external;
@@ -182,10 +197,12 @@ void aio_set_event_notifier(AioContext *ctx,
EventNotifier *notifier,
bool is_external,
EventNotifierHandler *io_read,
- AioPollFn *io_poll)
+ AioPollFn *io_poll,
+ EventNotifierHandler *io_poll_ready)
{
aio_set_fd_handler(ctx, event_notifier_get_fd(notifier), is_external,
- (IOHandler *)io_read, NULL, io_poll, notifier);
+ (IOHandler *)io_read, NULL, io_poll,
+ (IOHandler *)io_poll_ready, notifier);
}
void aio_set_event_notifier_poll(AioContext *ctx,
@@ -198,7 +215,8 @@ void aio_set_event_notifier_poll(AioContext *ctx,
(IOHandler *)io_poll_end);
}
-static bool poll_set_started(AioContext *ctx, bool started)
+static bool poll_set_started(AioContext *ctx, AioHandlerList *ready_list,
+ bool started)
{
AioHandler *node;
bool progress = false;
@@ -228,8 +246,9 @@ static bool poll_set_started(AioContext *ctx, bool started)
}
/* Poll one last time in case ->io_poll_end() raced with the event */
- if (!started) {
- progress = node->io_poll(node->opaque) || progress;
+ if (!started && node->io_poll(node->opaque)) {
+ aio_add_ready_handler(ready_list, node, REVENTS_POLL_READY);
+ progress = true;
}
}
qemu_lockcnt_dec(&ctx->list_lock);
@@ -240,8 +259,11 @@ static bool poll_set_started(AioContext *ctx, bool started)
bool aio_prepare(AioContext *ctx)
{
+ AioHandlerList ready_list = QLIST_HEAD_INITIALIZER(ready_list);
+
/* Poll mode cannot be used with glib's event loop, disable it. */
- poll_set_started(ctx, false);
+ poll_set_started(ctx, &ready_list, false);
+ /* TODO what to do with this list? */
return false;
}
@@ -321,6 +343,18 @@ static bool aio_dispatch_handler(AioContext *ctx, AioHandler *node)
}
QLIST_INSERT_HEAD(&ctx->poll_aio_handlers, node, node_poll);
}
+ if (!QLIST_IS_INSERTED(node, node_deleted) &&
+ revents == 0 &&
+ aio_node_check(ctx, node->is_external) &&
+ node->io_poll_ready) {
+ node->io_poll_ready(node->opaque);
+
+ /*
+ * Return early since revents was zero. aio_notify() does not count as
+ * progress.
+ */
+ return node->opaque != &ctx->notifier;
+ }
if (!QLIST_IS_INSERTED(node, node_deleted) &&
(revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) &&
@@ -387,6 +421,7 @@ void aio_dispatch(AioContext *ctx)
}
static bool run_poll_handlers_once(AioContext *ctx,
+ AioHandlerList *ready_list,
int64_t now,
int64_t *timeout)
{
@@ -397,6 +432,8 @@ static bool run_poll_handlers_once(AioContext *ctx,
QLIST_FOREACH_SAFE(node, &ctx->poll_aio_handlers, node_poll, tmp) {
if (aio_node_check(ctx, node->is_external) &&
node->io_poll(node->opaque)) {
+ aio_add_ready_handler(ready_list, node, REVENTS_POLL_READY);
+
node->poll_idle_timeout = now + POLL_IDLE_INTERVAL_NS;
/*
@@ -420,7 +457,9 @@ static bool fdmon_supports_polling(AioContext *ctx)
return ctx->fdmon_ops->need_wait != aio_poll_disabled;
}
-static bool remove_idle_poll_handlers(AioContext *ctx, int64_t now)
+static bool remove_idle_poll_handlers(AioContext *ctx,
+ AioHandlerList *ready_list,
+ int64_t now)
{
AioHandler *node;
AioHandler *tmp;
@@ -451,7 +490,11 @@ static bool remove_idle_poll_handlers(AioContext *ctx, int64_t now)
* Nevermind about re-adding the handler in the rare case where
* this causes progress.
*/
- progress = node->io_poll(node->opaque) || progress;
+ if (node->io_poll(node->opaque)) {
+ aio_add_ready_handler(ready_list, node,
+ REVENTS_POLL_READY);
+ progress = true;
+ }
}
}
}
@@ -461,6 +504,7 @@ static bool remove_idle_poll_handlers(AioContext *ctx, int64_t now)
/* run_poll_handlers:
* @ctx: the AioContext
+ * @ready_list: the list to place ready handlers on
* @max_ns: maximum time to poll for, in nanoseconds
*
* Polls for a given time.
@@ -469,7 +513,8 @@ static bool remove_idle_poll_handlers(AioContext *ctx, int64_t now)
*
* Returns: true if progress was made, false otherwise
*/
-static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
+static bool run_poll_handlers(AioContext *ctx, AioHandlerList *ready_list,
+ int64_t max_ns, int64_t *timeout)
{
bool progress;
int64_t start_time, elapsed_time;
@@ -490,13 +535,15 @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
start_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
do {
- progress = run_poll_handlers_once(ctx, start_time, timeout);
+ progress = run_poll_handlers_once(ctx, ready_list,
+ start_time, timeout);
elapsed_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - start_time;
max_ns = qemu_soonest_timeout(*timeout, max_ns);
assert(!(max_ns && progress));
} while (elapsed_time < max_ns && !ctx->fdmon_ops->need_wait(ctx));
- if (remove_idle_poll_handlers(ctx, start_time + elapsed_time)) {
+ if (remove_idle_poll_handlers(ctx, ready_list,
+ start_time + elapsed_time)) {
*timeout = 0;
progress = true;
}
@@ -514,6 +561,7 @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
/* try_poll_mode:
* @ctx: the AioContext
+ * @ready_list: list to add handlers that need to be run
* @timeout: timeout for blocking wait, computed by the caller and updated if
* polling succeeds.
*
@@ -521,7 +569,8 @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
*
* Returns: true if progress was made, false otherwise
*/
-static bool try_poll_mode(AioContext *ctx, int64_t *timeout)
+static bool try_poll_mode(AioContext *ctx, AioHandlerList *ready_list,
+ int64_t *timeout)
{
int64_t max_ns;
@@ -531,14 +580,14 @@ static bool try_poll_mode(AioContext *ctx, int64_t *timeout)
max_ns = qemu_soonest_timeout(*timeout, ctx->poll_ns);
if (max_ns && !ctx->fdmon_ops->need_wait(ctx)) {
- poll_set_started(ctx, true);
+ poll_set_started(ctx, ready_list, true);
- if (run_poll_handlers(ctx, max_ns, timeout)) {
+ if (run_poll_handlers(ctx, ready_list, max_ns, timeout)) {
return true;
}
}
- if (poll_set_started(ctx, false)) {
+ if (poll_set_started(ctx, ready_list, false)) {
*timeout = 0;
return true;
}
@@ -549,7 +598,6 @@ static bool try_poll_mode(AioContext *ctx, int64_t *timeout)
bool aio_poll(AioContext *ctx, bool blocking)
{
AioHandlerList ready_list = QLIST_HEAD_INITIALIZER(ready_list);
- int ret = 0;
bool progress;
bool use_notify_me;
int64_t timeout;
@@ -574,7 +622,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
}
timeout = blocking ? aio_compute_timeout(ctx) : 0;
- progress = try_poll_mode(ctx, &timeout);
+ progress = try_poll_mode(ctx, &ready_list, &timeout);
assert(!(timeout && progress));
/*
@@ -604,7 +652,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
* system call---a single round of run_poll_handlers_once suffices.
*/
if (timeout || ctx->fdmon_ops->need_wait(ctx)) {
- ret = ctx->fdmon_ops->wait(ctx, &ready_list, timeout);
+ ctx->fdmon_ops->wait(ctx, &ready_list, timeout);
}
if (use_notify_me) {
@@ -657,10 +705,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
}
progress |= aio_bh_poll(ctx);
-
- if (ret > 0) {
- progress |= aio_dispatch_ready_handlers(ctx, &ready_list);
- }
+ progress |= aio_dispatch_ready_handlers(ctx, &ready_list);
aio_free_deleted_handlers(ctx);
diff --git a/util/aio-posix.h b/util/aio-posix.h
index c80c04506a..7f2c37a684 100644
--- a/util/aio-posix.h
+++ b/util/aio-posix.h
@@ -24,6 +24,7 @@ struct AioHandler {
IOHandler *io_read;
IOHandler *io_write;
AioPollFn *io_poll;
+ IOHandler *io_poll_ready;
IOHandler *io_poll_begin;
IOHandler *io_poll_end;
void *opaque;
diff --git a/util/aio-win32.c b/util/aio-win32.c
index d5b09a1193..7aac89df3a 100644
--- a/util/aio-win32.c
+++ b/util/aio-win32.c
@@ -68,6 +68,7 @@ void aio_set_fd_handler(AioContext *ctx,
IOHandler *io_read,
IOHandler *io_write,
AioPollFn *io_poll,
+ IOHandler *io_poll_ready,
void *opaque)
{
/* fd is a SOCKET in our case */
@@ -136,7 +137,8 @@ void aio_set_event_notifier(AioContext *ctx,
EventNotifier *e,
bool is_external,
EventNotifierHandler *io_notify,
- AioPollFn *io_poll)
+ AioPollFn *io_poll,
+ EventNotifierHandler *io_poll_ready)
{
AioHandler *node;
diff --git a/util/async.c b/util/async.c
index 6f6717a34b..08d25feef5 100644
--- a/util/async.c
+++ b/util/async.c
@@ -362,7 +362,7 @@ aio_ctx_finalize(GSource *source)
g_free(bh);
}
- aio_set_event_notifier(ctx, &ctx->notifier, false, NULL, NULL);
+ aio_set_event_notifier(ctx, &ctx->notifier, false, NULL, NULL, NULL);
event_notifier_cleanup(&ctx->notifier);
qemu_rec_mutex_destroy(&ctx->lock);
qemu_lockcnt_destroy(&ctx->list_lock);
@@ -485,6 +485,11 @@ static bool aio_context_notifier_poll(void *opaque)
return qatomic_read(&ctx->notified);
}
+static void aio_context_notifier_poll_ready(EventNotifier *e)
+{
+ /* Do nothing, we just wanted to kick the event loop */
+}
+
static void co_schedule_bh_cb(void *opaque)
{
AioContext *ctx = opaque;
@@ -536,7 +541,8 @@ AioContext *aio_context_new(Error **errp)
aio_set_event_notifier(ctx, &ctx->notifier,
false,
aio_context_notifier_cb,
- aio_context_notifier_poll);
+ aio_context_notifier_poll,
+ aio_context_notifier_poll_ready);
#ifdef CONFIG_LINUX_AIO
ctx->linux_aio = NULL;
#endif
diff --git a/util/main-loop.c b/util/main-loop.c
index 06b18b195c..4d5a5b9943 100644
--- a/util/main-loop.c
+++ b/util/main-loop.c
@@ -582,7 +582,7 @@ void qemu_set_fd_handler(int fd,
{
iohandler_init();
aio_set_fd_handler(iohandler_ctx, fd, false,
- fd_read, fd_write, NULL, opaque);
+ fd_read, fd_write, NULL, NULL, opaque);
}
void event_notifier_set_handler(EventNotifier *e,
@@ -590,5 +590,5 @@ void event_notifier_set_handler(EventNotifier *e,
{
iohandler_init();
aio_set_event_notifier(iohandler_ctx, e, false,
- handler, NULL);
+ handler, NULL, NULL);
}
diff --git a/util/meson.build b/util/meson.build
index e676b2f6c6..c9a9cc1cf5 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -84,7 +84,10 @@ if have_block
util_ss.add(files('readline.c'))
util_ss.add(files('throttle.c'))
util_ss.add(files('timed-average.c'))
- util_ss.add(when: 'CONFIG_INOTIFY1', if_true: files('filemonitor-inotify.c'),
- if_false: files('filemonitor-stub.c'))
+ if config_host_data.get('CONFIG_INOTIFY1')
+ util_ss.add(files('filemonitor-inotify.c'))
+ else
+ util_ss.add(files('filemonitor-stub.c'))
+ endif
util_ss.add(when: 'CONFIG_LINUX', if_true: files('vfio-helpers.c'))
endif
diff --git a/util/qemu-coroutine-io.c b/util/qemu-coroutine-io.c
index 5b80bb416f..7f5839cb76 100644
--- a/util/qemu-coroutine-io.c
+++ b/util/qemu-coroutine-io.c
@@ -75,7 +75,8 @@ typedef struct {
static void fd_coroutine_enter(void *opaque)
{
FDYieldUntilData *data = opaque;
- aio_set_fd_handler(data->ctx, data->fd, false, NULL, NULL, NULL, NULL);
+ aio_set_fd_handler(data->ctx, data->fd, false,
+ NULL, NULL, NULL, NULL, NULL);
qemu_coroutine_enter(data->co);
}
@@ -88,6 +89,6 @@ void coroutine_fn yield_until_fd_readable(int fd)
data.co = qemu_coroutine_self();
data.fd = fd;
aio_set_fd_handler(
- data.ctx, fd, false, fd_coroutine_enter, NULL, NULL, &data);
+ data.ctx, fd, false, fd_coroutine_enter, NULL, NULL, NULL, &data);
qemu_coroutine_yield();
}
diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c
index 783d847a6d..f68287e811 100644
--- a/util/vhost-user-server.c
+++ b/util/vhost-user-server.c
@@ -250,7 +250,7 @@ set_watch(VuDev *vu_dev, int fd, int vu_evt,
vu_fd_watch->cb = cb;
qemu_set_nonblock(fd);
aio_set_fd_handler(server->ioc->ctx, fd, true, kick_handler,
- NULL, NULL, vu_fd_watch);
+ NULL, NULL, NULL, vu_fd_watch);
vu_fd_watch->vu_dev = vu_dev;
vu_fd_watch->pvt = pvt;
}
@@ -270,7 +270,8 @@ static void remove_watch(VuDev *vu_dev, int fd)
if (!vu_fd_watch) {
return;
}
- aio_set_fd_handler(server->ioc->ctx, fd, true, NULL, NULL, NULL, NULL);
+ aio_set_fd_handler(server->ioc->ctx, fd, true,
+ NULL, NULL, NULL, NULL, NULL);
QTAILQ_REMOVE(&server->vu_fd_watches, vu_fd_watch, next);
g_free(vu_fd_watch);
@@ -334,7 +335,7 @@ void vhost_user_server_stop(VuServer *server)
QTAILQ_FOREACH(vu_fd_watch, &server->vu_fd_watches, next) {
aio_set_fd_handler(server->ctx, vu_fd_watch->fd, true,
- NULL, NULL, NULL, vu_fd_watch);
+ NULL, NULL, NULL, NULL, vu_fd_watch);
}
qio_channel_shutdown(server->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
@@ -377,7 +378,7 @@ void vhost_user_server_attach_aio_context(VuServer *server, AioContext *ctx)
QTAILQ_FOREACH(vu_fd_watch, &server->vu_fd_watches, next) {
aio_set_fd_handler(ctx, vu_fd_watch->fd, true, kick_handler, NULL,
- NULL, vu_fd_watch);
+ NULL, NULL, vu_fd_watch);
}
aio_co_schedule(ctx, server->co_trip);
@@ -391,7 +392,7 @@ void vhost_user_server_detach_aio_context(VuServer *server)
QTAILQ_FOREACH(vu_fd_watch, &server->vu_fd_watches, next) {
aio_set_fd_handler(server->ctx, vu_fd_watch->fd, true,
- NULL, NULL, NULL, vu_fd_watch);
+ NULL, NULL, NULL, NULL, vu_fd_watch);
}
qio_channel_detach_aio_context(server->ioc);