summaryrefslogtreecommitdiffstats
path: root/debian/patches/v7.2.1.diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--debian/patches/v7.2.1.diff1945
1 files changed, 1945 insertions, 0 deletions
diff --git a/debian/patches/v7.2.1.diff b/debian/patches/v7.2.1.diff
new file mode 100644
index 00000000..a980f89e
--- /dev/null
+++ b/debian/patches/v7.2.1.diff
@@ -0,0 +1,1945 @@
+Subject: v7.2.1
+Date: Wed Apr 5 14:37:42 2023 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.0
+and upstream qemu v7.2.1.
+
+ VERSION | 2 +-
+ block/curl.c | 44 +++++--
+ block/io.c | 3 +
+ block/iscsi.c | 1 +
+ block/qcow2-bitmap.c | 5 +-
+ chardev/char-socket.c | 1 +
+ configure | 2 +-
+ hw/acpi/cpu_hotplug.c | 3 +
+ hw/core/machine.c | 3 +
+ hw/i386/intel_iommu.c | 15 +++
+ hw/i386/microvm.c | 2 +-
+ hw/i386/pc.c | 4 +-
+ hw/i386/pc_piix.c | 2 -
+ hw/i386/pc_q35.c | 2 -
+ hw/i386/x86.c | 88 +++----------
+ hw/nvme/ctrl.c | 32 ++++-
+ hw/nvram/fw_cfg.c | 12 +-
+ hw/smbios/smbios.c | 8 +-
+ hw/timer/hpet.c | 19 ++-
+ hw/virtio/vhost-shadow-virtqueue.c | 2 +-
+ hw/virtio/vhost-user-gpio.c | 10 +-
+ hw/virtio/vhost-user-i2c.c | 5 +-
+ hw/virtio/vhost-user-rng.c | 5 +-
+ hw/virtio/vhost-vdpa.c | 17 +--
+ hw/virtio/vhost.c | 84 ++++++++++---
+ hw/virtio/virtio-mem.c | 6 +-
+ include/hw/i386/pc.h | 3 -
+ include/hw/i386/x86.h | 3 +-
+ include/hw/nvram/fw_cfg.h | 22 ----
+ include/hw/virtio/vhost-user-gpio.h | 2 +-
+ meson.build | 2 +-
+ migration/ram.c | 9 +-
+ scripts/shaderinclude.pl | 16 ---
+ scripts/shaderinclude.py | 26 ++++
+ scripts/symlink-install-tree.py | 1 -
+ subprojects/libvhost-user/libvhost-user.c | 7 ++
+ target/arm/helper.c | 3 +
+ target/arm/ptw.c | 6 +-
+ target/arm/sve_helper.c | 14 ++-
+ target/arm/translate.c | 2 +-
+ target/i386/tcg/emit.c.inc | 59 +++++----
+ target/riscv/translate.c | 12 +-
+ target/sh4/cpu.c | 2 +-
+ tests/tcg/Makefile.target | 2 +
+ tests/tcg/i386/Makefile.target | 6 +-
+ tests/tcg/i386/test-i386-adcox.c | 75 ++++++++++++
+ tests/tcg/i386/test-i386-bmi2.c | 197 ++++++++++++++++--------------
+ tests/tcg/multiarch/linux/linux-test.c | 6 +-
+ tests/tcg/riscv64/Makefile.target | 6 +
+ tests/tcg/riscv64/test-noc.S | 32 +++++
+ 50 files changed, 548 insertions(+), 342 deletions(-)
+
+diff --git a/VERSION b/VERSION
+index 0ee843cc60..b26a34e470 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.0
++7.2.1
+diff --git a/block/curl.c b/block/curl.c
+index cba4c4cac7..0b125095e3 100644
+--- a/block/curl.c
++++ b/block/curl.c
+@@ -37,8 +37,15 @@
+
+ // #define DEBUG_VERBOSE
+
++/* CURL 7.85.0 switches to a string based API for specifying
++ * the desired protocols.
++ */
++#if LIBCURL_VERSION_NUM >= 0x075500
++#define PROTOCOLS "HTTP,HTTPS,FTP,FTPS"
++#else
+ #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \
+ CURLPROTO_FTP | CURLPROTO_FTPS)
++#endif
+
+ #define CURL_NUM_STATES 8
+ #define CURL_NUM_ACB 8
+@@ -509,9 +516,18 @@ static int curl_init_state(BDRVCURLState *s, CURLState *state)
+ * obscure protocols. For example, do not allow POP3/SMTP/IMAP see
+ * CVE-2013-0249.
+ *
+- * Restricting protocols is only supported from 7.19.4 upwards.
++ * Restricting protocols is only supported from 7.19.4 upwards. Note:
++ * version 7.85.0 deprecates CURLOPT_*PROTOCOLS in favour of a string
++ * based CURLOPT_*PROTOCOLS_STR API.
+ */
+-#if LIBCURL_VERSION_NUM >= 0x071304
++#if LIBCURL_VERSION_NUM >= 0x075500
++ if (curl_easy_setopt(state->curl,
++ CURLOPT_PROTOCOLS_STR, PROTOCOLS) ||
++ curl_easy_setopt(state->curl,
++ CURLOPT_REDIR_PROTOCOLS_STR, PROTOCOLS)) {
++ goto err;
++ }
++#elif LIBCURL_VERSION_NUM >= 0x071304
+ if (curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS) ||
+ curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS)) {
+ goto err;
+@@ -669,7 +685,12 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
+ const char *file;
+ const char *cookie;
+ const char *cookie_secret;
+- double d;
++ /* CURL >= 7.55.0 uses curl_off_t for content length instead of a double */
++#if LIBCURL_VERSION_NUM >= 0x073700
++ curl_off_t cl;
++#else
++ double cl;
++#endif
+ const char *secretid;
+ const char *protocol_delimiter;
+ int ret;
+@@ -796,27 +817,36 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
+ }
+ if (curl_easy_perform(state->curl))
+ goto out;
+- if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) {
++ /* CURL 7.55.0 deprecates CURLINFO_CONTENT_LENGTH_DOWNLOAD in favour of
++ * the *_T version which returns a more sensible type for content length.
++ */
++#if LIBCURL_VERSION_NUM >= 0x073700
++ if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &cl)) {
++ goto out;
++ }
++#else
++ if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl)) {
+ goto out;
+ }
++#endif
+ /* Prior CURL 7.19.4 return value of 0 could mean that the file size is not
+ * know or the size is zero. From 7.19.4 CURL returns -1 if size is not
+ * known and zero if it is really zero-length file. */
+ #if LIBCURL_VERSION_NUM >= 0x071304
+- if (d < 0) {
++ if (cl < 0) {
+ pstrcpy(state->errmsg, CURL_ERROR_SIZE,
+ "Server didn't report file size.");
+ goto out;
+ }
+ #else
+- if (d <= 0) {
++ if (cl <= 0) {
+ pstrcpy(state->errmsg, CURL_ERROR_SIZE,
+ "Unknown file size or zero-length file.");
+ goto out;
+ }
+ #endif
+
+- s->len = d;
++ s->len = cl;
+
+ if ((!strncasecmp(s->url, "http://", strlen("http://"))
+ || !strncasecmp(s->url, "https://", strlen("https://")))
+diff --git a/block/io.c b/block/io.c
+index b9424024f9..bbaa0d1b2d 100644
+--- a/block/io.c
++++ b/block/io.c
+@@ -2087,6 +2087,9 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
+ if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) {
+ flags |= BDRV_REQ_MAY_UNMAP;
+ }
++
++ /* Can't use optimization hint with bufferless zero write */
++ flags &= ~BDRV_REQ_REGISTERED_BUF;
+ }
+
+ if (ret < 0) {
+diff --git a/block/iscsi.c b/block/iscsi.c
+index a316d46d96..1bba42a71b 100644
+--- a/block/iscsi.c
++++ b/block/iscsi.c
+@@ -268,6 +268,7 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
+ timer_mod(&iTask->retry_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + retry_time);
+ iTask->do_retry = 1;
++ return;
+ } else if (status == SCSI_STATUS_CHECK_CONDITION) {
+ int error = iscsi_translate_sense(&task->sense);
+ if (error == EAGAIN) {
+diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
+index bcad567c0c..3dff99ba06 100644
+--- a/block/qcow2-bitmap.c
++++ b/block/qcow2-bitmap.c
+@@ -115,7 +115,7 @@ static int update_header_sync(BlockDriverState *bs)
+ return bdrv_flush(bs->file->bs);
+ }
+
+-static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
++static inline void bitmap_table_bswap_be(uint64_t *bitmap_table, size_t size)
+ {
+ size_t i;
+
+@@ -1401,9 +1401,10 @@ static int store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp)
+ goto fail;
+ }
+
+- bitmap_table_to_be(tb, tb_size);
++ bitmap_table_bswap_be(tb, tb_size);
+ ret = bdrv_pwrite(bs->file, tb_offset, tb_size * sizeof(tb[0]), tb, 0);
+ if (ret < 0) {
++ bitmap_table_bswap_be(tb, tb_size);
+ error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",
+ bm_name);
+ goto fail;
+diff --git a/chardev/char-socket.c b/chardev/char-socket.c
+index 879564aa8a..b00efb1482 100644
+--- a/chardev/char-socket.c
++++ b/chardev/char-socket.c
+@@ -1065,6 +1065,7 @@ static void char_socket_finalize(Object *obj)
+ qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
+ NULL, chr->gcontext);
+ object_unref(OBJECT(s->listener));
++ s->listener = NULL;
+ }
+ if (s->tls_creds) {
+ object_unref(OBJECT(s->tls_creds));
+diff --git a/configure b/configure
+index 26c7bc5154..5f1828f1ec 100755
+--- a/configure
++++ b/configure
+@@ -2416,7 +2416,7 @@ echo "QEMU_OBJCFLAGS=$QEMU_OBJCFLAGS" >> $config_host_mak
+ echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
+ echo "GLIB_LIBS=$glib_libs" >> $config_host_mak
+ echo "GLIB_BINDIR=$glib_bindir" >> $config_host_mak
+-echo "GLIB_VERSION=$(pkg-config --modversion glib-2.0)" >> $config_host_mak
++echo "GLIB_VERSION=$($pkg_config --modversion glib-2.0)" >> $config_host_mak
+ echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak
+ echo "EXESUF=$EXESUF" >> $config_host_mak
+
+diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
+index 53654f8638..ff14c3f410 100644
+--- a/hw/acpi/cpu_hotplug.c
++++ b/hw/acpi/cpu_hotplug.c
+@@ -52,6 +52,9 @@ static const MemoryRegionOps AcpiCpuHotplug_ops = {
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
++ .max_access_size = 4,
++ },
++ .impl = {
+ .max_access_size = 1,
+ },
+ };
+diff --git a/hw/core/machine.c b/hw/core/machine.c
+index 8d34caa31d..035d078a74 100644
+--- a/hw/core/machine.c
++++ b/hw/core/machine.c
+@@ -42,6 +42,9 @@
+
+ GlobalProperty hw_compat_7_1[] = {
+ { "virtio-device", "queue_reset", "false" },
++ { "virtio-rng-pci", "vectors", "0" },
++ { "virtio-rng-pci-transitional", "vectors", "0" },
++ { "virtio-rng-pci-non-transitional", "vectors", "0" },
+ };
+ const size_t hw_compat_7_1_len = G_N_ELEMENTS(hw_compat_7_1);
+
+diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
+index a08ee85edf..d025ef2873 100644
+--- a/hw/i386/intel_iommu.c
++++ b/hw/i386/intel_iommu.c
+@@ -3179,6 +3179,7 @@ static int vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
+ {
+ VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
+ IntelIOMMUState *s = vtd_as->iommu_state;
++ X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(s);
+
+ /* TODO: add support for VFIO and vhost users */
+ if (s->snoop_control) {
+@@ -3186,6 +3187,20 @@ static int vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
+ "Snoop Control with vhost or VFIO is not supported");
+ return -ENOTSUP;
+ }
++ if (!s->caching_mode && (new & IOMMU_NOTIFIER_MAP)) {
++ error_setg_errno(errp, ENOTSUP,
++ "device %02x.%02x.%x requires caching mode",
++ pci_bus_num(vtd_as->bus), PCI_SLOT(vtd_as->devfn),
++ PCI_FUNC(vtd_as->devfn));
++ return -ENOTSUP;
++ }
++ if (!x86_iommu->dt_supported && (new & IOMMU_NOTIFIER_DEVIOTLB_UNMAP)) {
++ error_setg_errno(errp, ENOTSUP,
++ "device %02x.%02x.%x requires device IOTLB mode",
++ pci_bus_num(vtd_as->bus), PCI_SLOT(vtd_as->devfn),
++ PCI_FUNC(vtd_as->devfn));
++ return -ENOTSUP;
++ }
+
+ /* Update per-address-space notifier flags */
+ vtd_as->notifier_flags = new;
+diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
+index 170a331e3f..b231ceda9a 100644
+--- a/hw/i386/microvm.c
++++ b/hw/i386/microvm.c
+@@ -330,7 +330,7 @@ static void microvm_memory_init(MicrovmMachineState *mms)
+ rom_set_fw(fw_cfg);
+
+ if (machine->kernel_filename != NULL) {
+- x86_load_linux(x86ms, fw_cfg, 0, true, false);
++ x86_load_linux(x86ms, fw_cfg, 0, true);
+ }
+
+ if (mms->option_roms) {
+diff --git a/hw/i386/pc.c b/hw/i386/pc.c
+index 546b703cb4..ec5a10534b 100644
+--- a/hw/i386/pc.c
++++ b/hw/i386/pc.c
+@@ -799,7 +799,7 @@ void xen_load_linux(PCMachineState *pcms)
+ rom_set_fw(fw_cfg);
+
+ x86_load_linux(x86ms, fw_cfg, pcmc->acpi_data_size,
+- pcmc->pvh_enabled, pcmc->legacy_no_rng_seed);
++ pcmc->pvh_enabled);
+ for (i = 0; i < nb_option_roms; i++) {
+ assert(!strcmp(option_rom[i].name, "linuxboot.bin") ||
+ !strcmp(option_rom[i].name, "linuxboot_dma.bin") ||
+@@ -1119,7 +1119,7 @@ void pc_memory_init(PCMachineState *pcms,
+
+ if (linux_boot) {
+ x86_load_linux(x86ms, fw_cfg, pcmc->acpi_data_size,
+- pcmc->pvh_enabled, pcmc->legacy_no_rng_seed);
++ pcmc->pvh_enabled);
+ }
+
+ for (i = 0; i < nb_option_roms; i++) {
+diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
+index 0ad0ed1603..24616bf924 100644
+--- a/hw/i386/pc_piix.c
++++ b/hw/i386/pc_piix.c
+@@ -449,11 +449,9 @@ DEFINE_I440FX_MACHINE(v7_2, "pc-i440fx-7.2", NULL,
+
+ static void pc_i440fx_7_1_machine_options(MachineClass *m)
+ {
+- PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
+ pc_i440fx_7_2_machine_options(m);
+ m->alias = NULL;
+ m->is_default = false;
+- pcmc->legacy_no_rng_seed = true;
+ compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len);
+ compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len);
+ }
+diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
+index a496bd6e74..f522874add 100644
+--- a/hw/i386/pc_q35.c
++++ b/hw/i386/pc_q35.c
+@@ -383,10 +383,8 @@ DEFINE_Q35_MACHINE(v7_2, "pc-q35-7.2", NULL,
+
+ static void pc_q35_7_1_machine_options(MachineClass *m)
+ {
+- PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
+ pc_q35_7_2_machine_options(m);
+ m->alias = NULL;
+- pcmc->legacy_no_rng_seed = true;
+ compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len);
+ compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len);
+ }
+diff --git a/hw/i386/x86.c b/hw/i386/x86.c
+index 78cc131926..80be3032cc 100644
+--- a/hw/i386/x86.c
++++ b/hw/i386/x86.c
+@@ -26,7 +26,6 @@
+ #include "qemu/cutils.h"
+ #include "qemu/units.h"
+ #include "qemu/datadir.h"
+-#include "qemu/guest-random.h"
+ #include "qapi/error.h"
+ #include "qapi/qmp/qerror.h"
+ #include "qapi/qapi-visit-common.h"
+@@ -37,7 +36,6 @@
+ #include "sysemu/whpx.h"
+ #include "sysemu/numa.h"
+ #include "sysemu/replay.h"
+-#include "sysemu/reset.h"
+ #include "sysemu/sysemu.h"
+ #include "sysemu/cpu-timers.h"
+ #include "sysemu/xen.h"
+@@ -657,12 +655,12 @@ DeviceState *ioapic_init_secondary(GSIState *gsi_state)
+ return dev;
+ }
+
+-typedef struct SetupData {
++struct setup_data {
+ uint64_t next;
+ uint32_t type;
+ uint32_t len;
+ uint8_t data[];
+-} __attribute__((packed)) SetupData;
++} __attribute__((packed));
+
+
+ /*
+@@ -769,35 +767,10 @@ static bool load_elfboot(const char *kernel_filename,
+ return true;
+ }
+
+-typedef struct SetupDataFixup {
+- void *pos;
+- hwaddr orig_val, new_val;
+- uint32_t addr;
+-} SetupDataFixup;
+-
+-static void fixup_setup_data(void *opaque)
+-{
+- SetupDataFixup *fixup = opaque;
+- stq_p(fixup->pos, fixup->new_val);
+-}
+-
+-static void reset_setup_data(void *opaque)
+-{
+- SetupDataFixup *fixup = opaque;
+- stq_p(fixup->pos, fixup->orig_val);
+-}
+-
+-static void reset_rng_seed(void *opaque)
+-{
+- SetupData *setup_data = opaque;
+- qemu_guest_getrandom_nofail(setup_data->data, le32_to_cpu(setup_data->len));
+-}
+-
+ void x86_load_linux(X86MachineState *x86ms,
+ FWCfgState *fw_cfg,
+ int acpi_data_size,
+- bool pvh_enabled,
+- bool legacy_no_rng_seed)
++ bool pvh_enabled)
+ {
+ bool linuxboot_dma_enabled = X86_MACHINE_GET_CLASS(x86ms)->fwcfg_dma_enabled;
+ uint16_t protocol;
+@@ -805,17 +778,16 @@ void x86_load_linux(X86MachineState *x86ms,
+ int dtb_size, setup_data_offset;
+ uint32_t initrd_max;
+ uint8_t header[8192], *setup, *kernel;
+- hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0, first_setup_data = 0;
++ hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
+ FILE *f;
+ char *vmode;
+ MachineState *machine = MACHINE(x86ms);
+- SetupData *setup_data;
++ struct setup_data *setup_data;
+ const char *kernel_filename = machine->kernel_filename;
+ const char *initrd_filename = machine->initrd_filename;
+ const char *dtb_filename = machine->dtb;
+ const char *kernel_cmdline = machine->kernel_cmdline;
+ SevKernelLoaderContext sev_load_ctx = {};
+- enum { RNG_SEED_LENGTH = 32 };
+
+ /* Align to 16 bytes as a paranoia measure */
+ cmdline_size = (strlen(kernel_cmdline) + 16) & ~15;
+@@ -1092,41 +1064,19 @@ void x86_load_linux(X86MachineState *x86ms,
+ }
+
+ setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16);
+- kernel_size = setup_data_offset + sizeof(SetupData) + dtb_size;
++ kernel_size = setup_data_offset + sizeof(struct setup_data) + dtb_size;
+ kernel = g_realloc(kernel, kernel_size);
+
++ stq_p(header + 0x250, prot_addr + setup_data_offset);
+
+- setup_data = (SetupData *)(kernel + setup_data_offset);
+- setup_data->next = cpu_to_le64(first_setup_data);
+- first_setup_data = prot_addr + setup_data_offset;
++ setup_data = (struct setup_data *)(kernel + setup_data_offset);
++ setup_data->next = 0;
+ setup_data->type = cpu_to_le32(SETUP_DTB);
+ setup_data->len = cpu_to_le32(dtb_size);
+
+ load_image_size(dtb_filename, setup_data->data, dtb_size);
+ }
+
+- if (!legacy_no_rng_seed) {
+- setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16);
+- kernel_size = setup_data_offset + sizeof(SetupData) + RNG_SEED_LENGTH;
+- kernel = g_realloc(kernel, kernel_size);
+- setup_data = (SetupData *)(kernel + setup_data_offset);
+- setup_data->next = cpu_to_le64(first_setup_data);
+- first_setup_data = prot_addr + setup_data_offset;
+- setup_data->type = cpu_to_le32(SETUP_RNG_SEED);
+- setup_data->len = cpu_to_le32(RNG_SEED_LENGTH);
+- qemu_guest_getrandom_nofail(setup_data->data, RNG_SEED_LENGTH);
+- qemu_register_reset_nosnapshotload(reset_rng_seed, setup_data);
+- fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_KERNEL_DATA, reset_rng_seed, NULL,
+- setup_data, kernel, kernel_size, true);
+- } else {
+- fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
+- }
+-
+- fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
+- fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+- sev_load_ctx.kernel_data = (char *)kernel;
+- sev_load_ctx.kernel_size = kernel_size;
+-
+ /*
+ * If we're starting an encrypted VM, it will be OVMF based, which uses the
+ * efi stub for booting and doesn't require any values to be placed in the
+@@ -1135,20 +1085,16 @@ void x86_load_linux(X86MachineState *x86ms,
+ * file the user passed in.
+ */
+ if (!sev_enabled()) {
+- SetupDataFixup *fixup = g_malloc(sizeof(*fixup));
+-
+ memcpy(setup, header, MIN(sizeof(header), setup_size));
+- /* Offset 0x250 is a pointer to the first setup_data link. */
+- fixup->pos = setup + 0x250;
+- fixup->orig_val = ldq_p(fixup->pos);
+- fixup->new_val = first_setup_data;
+- fixup->addr = cpu_to_le32(real_addr);
+- fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_SETUP_ADDR, fixup_setup_data, NULL,
+- fixup, &fixup->addr, sizeof(fixup->addr), true);
+- qemu_register_reset(reset_setup_data, fixup);
+- } else {
+- fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
+ }
++
++ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
++ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
++ fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
++ sev_load_ctx.kernel_data = (char *)kernel;
++ sev_load_ctx.kernel_size = kernel_size;
++
++ fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
+ sev_load_ctx.setup_data = (char *)setup;
+diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
+index e54276dc1d..1d3e058452 100644
+--- a/hw/nvme/ctrl.c
++++ b/hw/nvme/ctrl.c
+@@ -1331,10 +1331,23 @@ static inline void nvme_blk_write(BlockBackend *blk, int64_t offset,
+ }
+ }
+
++static void nvme_update_cq_eventidx(const NvmeCQueue *cq)
++{
++ uint32_t v = cpu_to_le32(cq->head);
++
++ //not in 7.2: trace_pci_nvme_update_cq_eventidx(cq->cqid, cq->head);
++
++ pci_dma_write(PCI_DEVICE(cq->ctrl), cq->ei_addr, &v, sizeof(v));
++}
++
+ static void nvme_update_cq_head(NvmeCQueue *cq)
+ {
+- pci_dma_read(&cq->ctrl->parent_obj, cq->db_addr, &cq->head,
+- sizeof(cq->head));
++ uint32_t v;
++
++ pci_dma_read(&cq->ctrl->parent_obj, cq->db_addr, &v, sizeof(v));
++
++ cq->head = le32_to_cpu(v);
++
+ trace_pci_nvme_shadow_doorbell_cq(cq->cqid, cq->head);
+ }
+
+@@ -1351,6 +1364,7 @@ static void nvme_post_cqes(void *opaque)
+ hwaddr addr;
+
+ if (n->dbbuf_enabled) {
++ nvme_update_cq_eventidx(cq);
+ nvme_update_cq_head(cq);
+ }
+
+@@ -6141,15 +6155,21 @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeRequest *req)
+
+ static void nvme_update_sq_eventidx(const NvmeSQueue *sq)
+ {
+- pci_dma_write(&sq->ctrl->parent_obj, sq->ei_addr, &sq->tail,
+- sizeof(sq->tail));
++ uint32_t v = cpu_to_le32(sq->tail);
++
++ pci_dma_write(&sq->ctrl->parent_obj, sq->ei_addr, &v, sizeof(v));
++
+ trace_pci_nvme_eventidx_sq(sq->sqid, sq->tail);
+ }
+
+ static void nvme_update_sq_tail(NvmeSQueue *sq)
+ {
+- pci_dma_read(&sq->ctrl->parent_obj, sq->db_addr, &sq->tail,
+- sizeof(sq->tail));
++ uint32_t v;
++
++ pci_dma_read(&sq->ctrl->parent_obj, sq->db_addr, &v, sizeof(v));
++
++ sq->tail = le32_to_cpu(v);
++
+ trace_pci_nvme_shadow_doorbell_sq(sq->sqid, sq->tail);
+ }
+
+diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
+index 6edf5ea3e9..371a45dfe2 100644
+--- a/hw/nvram/fw_cfg.c
++++ b/hw/nvram/fw_cfg.c
+@@ -693,12 +693,12 @@ static const VMStateDescription vmstate_fw_cfg = {
+ }
+ };
+
+-void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key,
+- FWCfgCallback select_cb,
+- FWCfgWriteCallback write_cb,
+- void *callback_opaque,
+- void *data, size_t len,
+- bool read_only)
++static void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key,
++ FWCfgCallback select_cb,
++ FWCfgWriteCallback write_cb,
++ void *callback_opaque,
++ void *data, size_t len,
++ bool read_only)
+ {
+ int arch = !!(key & FW_CFG_ARCH_LOCAL);
+
+diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
+index b4243de735..66a020999b 100644
+--- a/hw/smbios/smbios.c
++++ b/hw/smbios/smbios.c
+@@ -749,14 +749,16 @@ static void smbios_build_type_4_table(MachineState *ms, unsigned instance)
+ t->core_count = (ms->smp.cores > 255) ? 0xFF : ms->smp.cores;
+ t->core_enabled = t->core_count;
+
+- t->core_count2 = t->core_enabled2 = cpu_to_le16(ms->smp.cores);
+-
+ t->thread_count = (ms->smp.threads > 255) ? 0xFF : ms->smp.threads;
+- t->thread_count2 = cpu_to_le16(ms->smp.threads);
+
+ t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */
+ t->processor_family2 = cpu_to_le16(0x01); /* Other */
+
++ if (tbl_len == SMBIOS_TYPE_4_LEN_V30) {
++ t->core_count2 = t->core_enabled2 = cpu_to_le16(ms->smp.cores);
++ t->thread_count2 = cpu_to_le16(ms->smp.threads);
++ }
++
+ SMBIOS_BUILD_TABLE_POST;
+ smbios_type4_count++;
+ }
+diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
+index 9520471be2..5f88ffdef8 100644
+--- a/hw/timer/hpet.c
++++ b/hw/timer/hpet.c
+@@ -352,6 +352,16 @@ static const VMStateDescription vmstate_hpet = {
+ }
+ };
+
++static void hpet_arm(HPETTimer *t, uint64_t ticks)
++{
++ if (ticks < ns_to_ticks(INT64_MAX / 2)) {
++ timer_mod(t->qemu_timer,
++ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks_to_ns(ticks));
++ } else {
++ timer_del(t->qemu_timer);
++ }
++}
++
+ /*
+ * timer expiration callback
+ */
+@@ -374,13 +384,11 @@ static void hpet_timer(void *opaque)
+ }
+ }
+ diff = hpet_calculate_diff(t, cur_tick);
+- timer_mod(t->qemu_timer,
+- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (int64_t)ticks_to_ns(diff));
++ hpet_arm(t, diff);
+ } else if (t->config & HPET_TN_32BIT && !timer_is_periodic(t)) {
+ if (t->wrap_flag) {
+ diff = hpet_calculate_diff(t, cur_tick);
+- timer_mod(t->qemu_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+- (int64_t)ticks_to_ns(diff));
++ hpet_arm(t, diff);
+ t->wrap_flag = 0;
+ }
+ }
+@@ -407,8 +415,7 @@ static void hpet_set_timer(HPETTimer *t)
+ t->wrap_flag = 1;
+ }
+ }
+- timer_mod(t->qemu_timer,
+- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (int64_t)ticks_to_ns(diff));
++ hpet_arm(t, diff);
+ }
+
+ static void hpet_del_timer(HPETTimer *t)
+diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
+index 5bd14cad96..a723073747 100644
+--- a/hw/virtio/vhost-shadow-virtqueue.c
++++ b/hw/virtio/vhost-shadow-virtqueue.c
+@@ -522,7 +522,7 @@ static void vhost_svq_flush(VhostShadowVirtqueue *svq,
+ size_t vhost_svq_poll(VhostShadowVirtqueue *svq)
+ {
+ int64_t start_us = g_get_monotonic_time();
+- uint32_t len;
++ uint32_t len = 0;
+
+ do {
+ if (vhost_svq_more_used(svq)) {
+diff --git a/hw/virtio/vhost-user-gpio.c b/hw/virtio/vhost-user-gpio.c
+index b7b82a1099..97145376eb 100644
+--- a/hw/virtio/vhost-user-gpio.c
++++ b/hw/virtio/vhost-user-gpio.c
+@@ -16,6 +16,7 @@
+ #include "trace.h"
+
+ #define REALIZE_CONNECTION_RETRIES 3
++#define VHOST_NVQS 2
+
+ /* Features required from VirtIO */
+ static const int feature_bits[] = {
+@@ -198,8 +199,7 @@ static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserGPIO *gpio)
+ {
+ virtio_delete_queue(gpio->command_vq);
+ virtio_delete_queue(gpio->interrupt_vq);
+- g_free(gpio->vhost_dev.vqs);
+- gpio->vhost_dev.vqs = NULL;
++ g_free(gpio->vhost_vqs);
+ virtio_cleanup(vdev);
+ vhost_user_cleanup(&gpio->vhost_user);
+ }
+@@ -219,6 +219,9 @@ static int vu_gpio_connect(DeviceState *dev, Error **errp)
+ vhost_dev_set_config_notifier(vhost_dev, &gpio_ops);
+ gpio->vhost_user.supports_config = true;
+
++ gpio->vhost_dev.nvqs = VHOST_NVQS;
++ gpio->vhost_dev.vqs = gpio->vhost_vqs;
++
+ ret = vhost_dev_init(vhost_dev, &gpio->vhost_user,
+ VHOST_BACKEND_TYPE_USER, 0, errp);
+ if (ret < 0) {
+@@ -337,10 +340,9 @@ static void vu_gpio_device_realize(DeviceState *dev, Error **errp)
+
+ virtio_init(vdev, VIRTIO_ID_GPIO, sizeof(gpio->config));
+
+- gpio->vhost_dev.nvqs = 2;
+ gpio->command_vq = virtio_add_queue(vdev, 256, vu_gpio_handle_output);
+ gpio->interrupt_vq = virtio_add_queue(vdev, 256, vu_gpio_handle_output);
+- gpio->vhost_dev.vqs = g_new0(struct vhost_virtqueue, gpio->vhost_dev.nvqs);
++ gpio->vhost_vqs = g_new0(struct vhost_virtqueue, VHOST_NVQS);
+
+ gpio->connected = false;
+
+diff --git a/hw/virtio/vhost-user-i2c.c b/hw/virtio/vhost-user-i2c.c
+index dc5c828ba6..60eaf0d95b 100644
+--- a/hw/virtio/vhost-user-i2c.c
++++ b/hw/virtio/vhost-user-i2c.c
+@@ -143,8 +143,6 @@ static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserI2C *i2c)
+ vhost_user_cleanup(&i2c->vhost_user);
+ virtio_delete_queue(i2c->vq);
+ virtio_cleanup(vdev);
+- g_free(i2c->vhost_dev.vqs);
+- i2c->vhost_dev.vqs = NULL;
+ }
+
+ static int vu_i2c_connect(DeviceState *dev)
+@@ -228,6 +226,7 @@ static void vu_i2c_device_realize(DeviceState *dev, Error **errp)
+ ret = vhost_dev_init(&i2c->vhost_dev, &i2c->vhost_user,
+ VHOST_BACKEND_TYPE_USER, 0, errp);
+ if (ret < 0) {
++ g_free(i2c->vhost_dev.vqs);
+ do_vhost_user_cleanup(vdev, i2c);
+ }
+
+@@ -239,10 +238,12 @@ static void vu_i2c_device_unrealize(DeviceState *dev)
+ {
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VHostUserI2C *i2c = VHOST_USER_I2C(dev);
++ struct vhost_virtqueue *vhost_vqs = i2c->vhost_dev.vqs;
+
+ /* This will stop vhost backend if appropriate. */
+ vu_i2c_set_status(vdev, 0);
+ vhost_dev_cleanup(&i2c->vhost_dev);
++ g_free(vhost_vqs);
+ do_vhost_user_cleanup(vdev, i2c);
+ }
+
+diff --git a/hw/virtio/vhost-user-rng.c b/hw/virtio/vhost-user-rng.c
+index 201a39e220..efc54cd3fb 100644
+--- a/hw/virtio/vhost-user-rng.c
++++ b/hw/virtio/vhost-user-rng.c
+@@ -229,6 +229,7 @@ static void vu_rng_device_realize(DeviceState *dev, Error **errp)
+ return;
+
+ vhost_dev_init_failed:
++ g_free(rng->vhost_dev.vqs);
+ virtio_delete_queue(rng->req_vq);
+ virtio_add_queue_failed:
+ virtio_cleanup(vdev);
+@@ -239,12 +240,12 @@ static void vu_rng_device_unrealize(DeviceState *dev)
+ {
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VHostUserRNG *rng = VHOST_USER_RNG(dev);
++ struct vhost_virtqueue *vhost_vqs = rng->vhost_dev.vqs;
+
+ vu_rng_set_status(vdev, 0);
+
+ vhost_dev_cleanup(&rng->vhost_dev);
+- g_free(rng->vhost_dev.vqs);
+- rng->vhost_dev.vqs = NULL;
++ g_free(vhost_vqs);
+ virtio_delete_queue(rng->req_vq);
+ virtio_cleanup(vdev);
+ vhost_user_cleanup(&rng->vhost_user);
+diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
+index 7468e44b87..03c78d25d8 100644
+--- a/hw/virtio/vhost-vdpa.c
++++ b/hw/virtio/vhost-vdpa.c
+@@ -707,26 +707,11 @@ static int vhost_vdpa_get_device_id(struct vhost_dev *dev,
+ return ret;
+ }
+
+-static void vhost_vdpa_reset_svq(struct vhost_vdpa *v)
+-{
+- if (!v->shadow_vqs_enabled) {
+- return;
+- }
+-
+- for (unsigned i = 0; i < v->shadow_vqs->len; ++i) {
+- VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
+- vhost_svq_stop(svq);
+- }
+-}
+-
+ static int vhost_vdpa_reset_device(struct vhost_dev *dev)
+ {
+- struct vhost_vdpa *v = dev->opaque;
+ int ret;
+ uint8_t status = 0;
+
+- vhost_vdpa_reset_svq(v);
+-
+ ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &status);
+ trace_vhost_vdpa_reset_device(dev, status);
+ return ret;
+@@ -1088,6 +1073,8 @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev)
+
+ for (unsigned i = 0; i < v->shadow_vqs->len; ++i) {
+ VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
++
++ vhost_svq_stop(svq);
+ vhost_vdpa_svq_unmap_rings(dev, svq);
+ }
+ }
+diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
+index 7fb008bc9e..fdcd1a8fdf 100644
+--- a/hw/virtio/vhost.c
++++ b/hw/virtio/vhost.c
+@@ -20,6 +20,7 @@
+ #include "qemu/range.h"
+ #include "qemu/error-report.h"
+ #include "qemu/memfd.h"
++#include "qemu/log.h"
+ #include "standard-headers/linux/vhost_types.h"
+ #include "hw/virtio/virtio-bus.h"
+ #include "hw/virtio/virtio-access.h"
+@@ -106,6 +107,24 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
+ }
+ }
+
++static bool vhost_dev_has_iommu(struct vhost_dev *dev)
++{
++ VirtIODevice *vdev = dev->vdev;
++
++ /*
++ * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support
++ * incremental memory mapping API via IOTLB API. For platform that
++ * does not have IOMMU, there's no need to enable this feature
++ * which may cause unnecessary IOTLB miss/update transactions.
++ */
++ if (vdev) {
++ return virtio_bus_device_iommu_enabled(vdev) &&
++ virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
++ } else {
++ return false;
++ }
++}
++
+ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
+ MemoryRegionSection *section,
+ hwaddr first,
+@@ -137,8 +156,51 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
+ continue;
+ }
+
+- vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys,
+- range_get_last(vq->used_phys, vq->used_size));
++ if (vhost_dev_has_iommu(dev)) {
++ IOMMUTLBEntry iotlb;
++ hwaddr used_phys = vq->used_phys, used_size = vq->used_size;
++ hwaddr phys, s, offset;
++
++ while (used_size) {
++ rcu_read_lock();
++ iotlb = address_space_get_iotlb_entry(dev->vdev->dma_as,
++ used_phys,
++ true,
++ MEMTXATTRS_UNSPECIFIED);
++ rcu_read_unlock();
++
++ if (!iotlb.target_as) {
++ qemu_log_mask(LOG_GUEST_ERROR, "translation "
++ "failure for used_iova %"PRIx64"\n",
++ used_phys);
++ return -EINVAL;
++ }
++
++ offset = used_phys & iotlb.addr_mask;
++ phys = iotlb.translated_addr + offset;
++
++ /*
++ * Distance from start of used ring until last byte of
++ * IOMMU page.
++ */
++ s = iotlb.addr_mask - offset;
++ /*
++ * Size of used ring, or of the part of it until end
++ * of IOMMU page. To avoid zero result, do the adding
++ * outside of MIN().
++ */
++ s = MIN(s, used_size - 1) + 1;
++
++ vhost_dev_sync_region(dev, section, start_addr, end_addr, phys,
++ range_get_last(phys, s));
++ used_size -= s;
++ used_phys += s;
++ }
++ } else {
++ vhost_dev_sync_region(dev, section, start_addr,
++ end_addr, vq->used_phys,
++ range_get_last(vq->used_phys, vq->used_size));
++ }
+ }
+ return 0;
+ }
+@@ -306,24 +368,6 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size)
+ dev->log_size = size;
+ }
+
+-static bool vhost_dev_has_iommu(struct vhost_dev *dev)
+-{
+- VirtIODevice *vdev = dev->vdev;
+-
+- /*
+- * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support
+- * incremental memory mapping API via IOTLB API. For platform that
+- * does not have IOMMU, there's no need to enable this feature
+- * which may cause unnecessary IOTLB miss/update transactions.
+- */
+- if (vdev) {
+- return virtio_bus_device_iommu_enabled(vdev) &&
+- virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
+- } else {
+- return false;
+- }
+-}
+-
+ static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr,
+ hwaddr *plen, bool is_write)
+ {
+diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
+index ed170def48..56db586c89 100644
+--- a/hw/virtio/virtio-mem.c
++++ b/hw/virtio/virtio-mem.c
+@@ -235,7 +235,7 @@ static int virtio_mem_for_each_plugged_section(const VirtIOMEM *vmem,
+ uint64_t offset, size;
+ int ret = 0;
+
+- first_bit = s->offset_within_region / vmem->bitmap_size;
++ first_bit = s->offset_within_region / vmem->block_size;
+ first_bit = find_next_bit(vmem->bitmap, vmem->bitmap_size, first_bit);
+ while (first_bit < vmem->bitmap_size) {
+ MemoryRegionSection tmp = *s;
+@@ -267,7 +267,7 @@ static int virtio_mem_for_each_unplugged_section(const VirtIOMEM *vmem,
+ uint64_t offset, size;
+ int ret = 0;
+
+- first_bit = s->offset_within_region / vmem->bitmap_size;
++ first_bit = s->offset_within_region / vmem->block_size;
+ first_bit = find_next_zero_bit(vmem->bitmap, vmem->bitmap_size, first_bit);
+ while (first_bit < vmem->bitmap_size) {
+ MemoryRegionSection tmp = *s;
+@@ -341,7 +341,7 @@ static int virtio_mem_notify_plug(VirtIOMEM *vmem, uint64_t offset,
+ if (ret) {
+ /* Notify all already-notified listeners. */
+ QLIST_FOREACH(rdl2, &vmem->rdl_list, next) {
+- MemoryRegionSection tmp = *rdl->section;
++ MemoryRegionSection tmp = *rdl2->section;
+
+ if (rdl2 == rdl) {
+ break;
+diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
+index c95333514e..0c76e82626 100644
+--- a/include/hw/i386/pc.h
++++ b/include/hw/i386/pc.h
+@@ -128,9 +128,6 @@ struct PCMachineClass {
+
+ /* create kvmclock device even when KVM PV features are not exposed */
+ bool kvmclock_create_always;
+-
+- /* skip passing an rng seed for legacy machines */
+- bool legacy_no_rng_seed;
+ };
+
+ #define TYPE_PC_MACHINE "generic-pc-machine"
+diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
+index 62fa5774f8..df82c5fd42 100644
+--- a/include/hw/i386/x86.h
++++ b/include/hw/i386/x86.h
+@@ -126,8 +126,7 @@ void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
+ void x86_load_linux(X86MachineState *x86ms,
+ FWCfgState *fw_cfg,
+ int acpi_data_size,
+- bool pvh_enabled,
+- bool legacy_no_rng_seed);
++ bool pvh_enabled);
+
+ bool x86_machine_is_smm_enabled(const X86MachineState *x86ms);
+ bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms);
+diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
+index 2e503904dc..c1f81a5f13 100644
+--- a/include/hw/nvram/fw_cfg.h
++++ b/include/hw/nvram/fw_cfg.h
+@@ -117,28 +117,6 @@ struct FWCfgMemState {
+ */
+ void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);
+
+-/**
+- * fw_cfg_add_bytes_callback:
+- * @s: fw_cfg device being modified
+- * @key: selector key value for new fw_cfg item
+- * @select_cb: callback function when selecting
+- * @write_cb: callback function after a write
+- * @callback_opaque: argument to be passed into callback function
+- * @data: pointer to start of item data
+- * @len: size of item data
+- * @read_only: is file read only
+- *
+- * Add a new fw_cfg item, available by selecting the given key, as a raw
+- * "blob" of the given size. The data referenced by the starting pointer
+- * is only linked, NOT copied, into the data structure of the fw_cfg device.
+- */
+-void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key,
+- FWCfgCallback select_cb,
+- FWCfgWriteCallback write_cb,
+- void *callback_opaque,
+- void *data, size_t len,
+- bool read_only);
+-
+ /**
+ * fw_cfg_add_string:
+ * @s: fw_cfg device being modified
+diff --git a/include/hw/virtio/vhost-user-gpio.h b/include/hw/virtio/vhost-user-gpio.h
+index a9305c5e6c..a9d3f9b049 100644
+--- a/include/hw/virtio/vhost-user-gpio.h
++++ b/include/hw/virtio/vhost-user-gpio.h
+@@ -23,7 +23,7 @@ struct VHostUserGPIO {
+ VirtIODevice parent_obj;
+ CharBackend chardev;
+ struct virtio_gpio_config config;
+- struct vhost_virtqueue *vhost_vq;
++ struct vhost_virtqueue *vhost_vqs;
+ struct vhost_dev vhost_dev;
+ VhostUserState vhost_user;
+ VirtQueue *command_vq;
+diff --git a/meson.build b/meson.build
+index 5c6b5a1c75..b88867ca9d 100644
+--- a/meson.build
++++ b/meson.build
+@@ -2777,7 +2777,7 @@ config_host_data.set('CONFIG_SLIRP', slirp.found())
+ genh += configure_file(output: 'config-host.h', configuration: config_host_data)
+
+ hxtool = find_program('scripts/hxtool')
+-shaderinclude = find_program('scripts/shaderinclude.pl')
++shaderinclude = find_program('scripts/shaderinclude.py')
+ qapi_gen = find_program('scripts/qapi-gen.py')
+ qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
+ meson.current_source_dir() / 'scripts/qapi/commands.py',
+diff --git a/migration/ram.c b/migration/ram.c
+index 1338e47665..f25ebd9620 100644
+--- a/migration/ram.c
++++ b/migration/ram.c
+@@ -1765,13 +1765,15 @@ out:
+ static inline void populate_read_range(RAMBlock *block, ram_addr_t offset,
+ ram_addr_t size)
+ {
++ const ram_addr_t end = offset + size;
++
+ /*
+ * We read one byte of each page; this will preallocate page tables if
+ * required and populate the shared zeropage on MAP_PRIVATE anonymous memory
+ * where no page was populated yet. This might require adaption when
+ * supporting other mappings, like shmem.
+ */
+- for (; offset < size; offset += block->page_size) {
++ for (; offset < end; offset += block->page_size) {
+ char tmp = *((char *)block->host + offset);
+
+ /* Don't optimize the read out */
+@@ -1885,13 +1887,14 @@ int ram_write_tracking_start(void)
+ block->max_length, UFFDIO_REGISTER_MODE_WP, NULL)) {
+ goto fail;
+ }
++ block->flags |= RAM_UF_WRITEPROTECT;
++ memory_region_ref(block->mr);
++
+ /* Apply UFFD write protection to the block memory range */
+ if (uffd_change_protection(rs->uffdio_fd, block->host,
+ block->max_length, true, false)) {
+ goto fail;
+ }
+- block->flags |= RAM_UF_WRITEPROTECT;
+- memory_region_ref(block->mr);
+
+ trace_ram_write_tracking_ramblock_start(block->idstr, block->page_size,
+ block->host, block->max_length);
+diff --git a/scripts/shaderinclude.pl b/scripts/shaderinclude.pl
+deleted file mode 100644
+index cd3bb40b12..0000000000
+--- a/scripts/shaderinclude.pl
++++ /dev/null
+@@ -1,16 +0,0 @@
+-#!/usr/bin/env perl
+-use strict;
+-use warnings;
+-
+-my $file = shift;
+-open FILE, "<", $file or die "open $file: $!";
+-my $name = $file;
+-$name =~ s|.*/||;
+-$name =~ s/[-.]/_/g;
+-print "static GLchar ${name}_src[] =\n";
+-while (<FILE>) {
+- chomp;
+- printf " \"%s\\n\"\n", $_;
+-}
+-print " \"\\n\";\n";
+-close FILE;
+diff --git a/scripts/shaderinclude.py b/scripts/shaderinclude.py
+new file mode 100644
+index 0000000000..ab2aade2cd
+--- /dev/null
++++ b/scripts/shaderinclude.py
+@@ -0,0 +1,26 @@
++#!/usr/bin/env python3
++#
++# Copyright (C) 2023 Red Hat, Inc.
++#
++# SPDX-License-Identifier: GPL-2.0-or-later
++
++import sys
++import os
++
++
++def main(args):
++ file_path = args[1]
++ basename = os.path.basename(file_path)
++ varname = basename.replace('-', '_').replace('.', '_')
++
++ with os.fdopen(sys.stdout.fileno(), "wt", closefd=False, newline='\n') as stdout:
++ with open(file_path, "r", encoding='utf-8') as file:
++ print(f'static GLchar {varname}_src[] =', file=stdout)
++ for line in file:
++ line = line.rstrip()
++ print(f' "{line}\\n"', file=stdout)
++ print(' "\\n";', file=stdout)
++
++
++if __name__ == '__main__':
++ sys.exit(main(sys.argv))
+diff --git a/scripts/symlink-install-tree.py b/scripts/symlink-install-tree.py
+index a5bf0b0d6d..67cb86dd52 100644
+--- a/scripts/symlink-install-tree.py
++++ b/scripts/symlink-install-tree.py
+@@ -17,7 +17,6 @@ def destdir_join(d1: str, d2: str) -> str:
+ out = subprocess.run([*introspect.split(' '), '--installed'],
+ stdout=subprocess.PIPE, check=True).stdout
+ for source, dest in json.loads(out).items():
+- assert os.path.isabs(source)
+ bundle_dest = destdir_join('qemu-bundle', dest)
+ path = os.path.dirname(bundle_dest)
+ try:
+diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
+index d6ee6e7d91..b17e82b2b0 100644
+--- a/subprojects/libvhost-user/libvhost-user.c
++++ b/subprojects/libvhost-user/libvhost-user.c
+@@ -2547,6 +2547,10 @@ virtqueue_alloc_element(size_t sz,
+
+ assert(sz >= sizeof(VuVirtqElement));
+ elem = malloc(out_sg_end);
++ if (!elem) {
++ DPRINT("%s: failed to malloc virtqueue element\n", __func__);
++ return NULL;
++ }
+ elem->out_num = out_num;
+ elem->in_num = in_num;
+ elem->in_sg = (void *)elem + in_sg_ofs;
+@@ -2633,6 +2637,9 @@ vu_queue_map_desc(VuDev *dev, VuVirtq *vq, unsigned int idx, size_t sz)
+
+ /* Now copy what we have collected and mapped */
+ elem = virtqueue_alloc_element(sz, out_num, in_num);
++ if (!elem) {
++ return NULL;
++ }
+ elem->index = idx;
+ for (i = 0; i < out_num; i++) {
+ elem->out_sg[i] = iov[i];
+diff --git a/target/arm/helper.c b/target/arm/helper.c
+index d8c8223ec3..22bc935242 100644
+--- a/target/arm/helper.c
++++ b/target/arm/helper.c
+@@ -1820,6 +1820,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+ if (cpu_isar_feature(aa64_sme, cpu)) {
+ valid_mask |= SCR_ENTP2;
+ }
++ if (cpu_isar_feature(aa64_hcx, cpu)) {
++ valid_mask |= SCR_HXEN;
++ }
+ } else {
+ valid_mask &= ~(SCR_RW | SCR_ST);
+ if (cpu_isar_feature(aa32_ras, cpu)) {
+diff --git a/target/arm/ptw.c b/target/arm/ptw.c
+index f812734bfb..0b16068557 100644
+--- a/target/arm/ptw.c
++++ b/target/arm/ptw.c
+@@ -238,8 +238,8 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
+ };
+ GetPhysAddrResult s2 = { };
+
+- if (!get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
+- false, &s2, fi)) {
++ if (get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
++ false, &s2, fi)) {
+ goto fail;
+ }
+ ptw->out_phys = s2.f.phys_addr;
+@@ -266,7 +266,7 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
+ if (unlikely(flags & TLB_INVALID_MASK)) {
+ goto fail;
+ }
+- ptw->out_phys = full->phys_addr;
++ ptw->out_phys = full->phys_addr | (addr & ~TARGET_PAGE_MASK);
+ ptw->out_rw = full->prot & PAGE_WRITE;
+ pte_attrs = full->pte_attrs;
+ pte_secure = full->attrs.secure;
+diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
+index 1afeadf9c8..521fc9b969 100644
+--- a/target/arm/sve_helper.c
++++ b/target/arm/sve_helper.c
+@@ -5354,15 +5354,10 @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
+ #ifdef CONFIG_USER_ONLY
+ flags = probe_access_flags(env, addr, access_type, mmu_idx, nofault,
+ &info->host, retaddr);
+- memset(&info->attrs, 0, sizeof(info->attrs));
+- /* Require both ANON and MTE; see allocation_tag_mem(). */
+- info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
+ #else
+ CPUTLBEntryFull *full;
+ flags = probe_access_full(env, addr, access_type, mmu_idx, nofault,
+ &info->host, &full, retaddr);
+- info->attrs = full->attrs;
+- info->tagged = full->pte_attrs == 0xf0;
+ #endif
+ info->flags = flags;
+
+@@ -5371,6 +5366,15 @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
+ return false;
+ }
+
++#ifdef CONFIG_USER_ONLY
++ memset(&info->attrs, 0, sizeof(info->attrs));
++ /* Require both ANON and MTE; see allocation_tag_mem(). */
++ info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
++#else
++ info->attrs = full->attrs;
++ info->tagged = full->pte_attrs == 0xf0;
++#endif
++
+ /* Ensure that info->host[] is relative to addr, not addr + mem_off. */
+ info->host -= mem_off;
+ return true;
+diff --git a/target/arm/translate.c b/target/arm/translate.c
+index 74a903072f..1dcaefb8e7 100644
+--- a/target/arm/translate.c
++++ b/target/arm/translate.c
+@@ -1184,7 +1184,7 @@ static inline void gen_hlt(DisasContext *s, int imm)
+ * semihosting, to provide some semblance of security
+ * (and for consistency with our 32-bit semihosting).
+ */
+- if (semihosting_enabled(s->current_el != 0) &&
++ if (semihosting_enabled(s->current_el == 0) &&
+ (imm == (s->thumb ? 0x3c : 0xf000))) {
+ gen_exception_internal_insn(s, EXCP_SEMIHOST);
+ return;
+diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
+index 7037ff91c6..7296f3952c 100644
+--- a/target/i386/tcg/emit.c.inc
++++ b/target/i386/tcg/emit.c.inc
+@@ -1015,6 +1015,7 @@ VSIB_AVX(VPGATHERQ, vpgatherq)
+
+ static void gen_ADCOX(DisasContext *s, CPUX86State *env, MemOp ot, int cc_op)
+ {
++ int opposite_cc_op;
+ TCGv carry_in = NULL;
+ TCGv carry_out = (cc_op == CC_OP_ADCX ? cpu_cc_dst : cpu_cc_src2);
+ TCGv zero;
+@@ -1022,14 +1023,8 @@ static void gen_ADCOX(DisasContext *s, CPUX86State *env, MemOp ot, int cc_op)
+ if (cc_op == s->cc_op || s->cc_op == CC_OP_ADCOX) {
+ /* Re-use the carry-out from a previous round. */
+ carry_in = carry_out;
+- cc_op = s->cc_op;
+- } else if (s->cc_op == CC_OP_ADCX || s->cc_op == CC_OP_ADOX) {
+- /* Merge with the carry-out from the opposite instruction. */
+- cc_op = CC_OP_ADCOX;
+- }
+-
+- /* If we don't have a carry-in, get it out of EFLAGS. */
+- if (!carry_in) {
++ } else {
++ /* We don't have a carry-in, get it out of EFLAGS. */
+ if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
+ gen_compute_eflags(s);
+ }
+@@ -1053,7 +1048,14 @@ static void gen_ADCOX(DisasContext *s, CPUX86State *env, MemOp ot, int cc_op)
+ tcg_gen_add2_tl(s->T0, carry_out, s->T0, carry_out, s->T1, zero);
+ break;
+ }
+- set_cc_op(s, cc_op);
++
++ opposite_cc_op = cc_op == CC_OP_ADCX ? CC_OP_ADOX : CC_OP_ADCX;
++ if (s->cc_op == CC_OP_ADCOX || s->cc_op == opposite_cc_op) {
++ /* Merge with the carry-out from the opposite instruction. */
++ set_cc_op(s, CC_OP_ADCOX);
++ } else {
++ set_cc_op(s, cc_op);
++ }
+ }
+
+ static void gen_ADCX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+@@ -1078,30 +1080,30 @@ static void gen_ANDN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ static void gen_BEXTR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ {
+ MemOp ot = decode->op[0].ot;
+- TCGv bound, zero;
++ TCGv bound = tcg_constant_tl(ot == MO_64 ? 63 : 31);
++ TCGv zero = tcg_constant_tl(0);
++ TCGv mone = tcg_constant_tl(-1);
+
+ /*
+ * Extract START, and shift the operand.
+ * Shifts larger than operand size get zeros.
+ */
+ tcg_gen_ext8u_tl(s->A0, s->T1);
++ if (TARGET_LONG_BITS == 64 && ot == MO_32) {
++ tcg_gen_ext32u_tl(s->T0, s->T0);
++ }
+ tcg_gen_shr_tl(s->T0, s->T0, s->A0);
+
+- bound = tcg_constant_tl(ot == MO_64 ? 63 : 31);
+- zero = tcg_constant_tl(0);
+ tcg_gen_movcond_tl(TCG_COND_LEU, s->T0, s->A0, bound, s->T0, zero);
+
+ /*
+- * Extract the LEN into a mask. Lengths larger than
+- * operand size get all ones.
++ * Extract the LEN into an inverse mask. Lengths larger than
++ * operand size get all zeros, length 0 gets all ones.
+ */
+ tcg_gen_extract_tl(s->A0, s->T1, 8, 8);
+- tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->A0, bound, s->A0, bound);
+-
+- tcg_gen_movi_tl(s->T1, 1);
+- tcg_gen_shl_tl(s->T1, s->T1, s->A0);
+- tcg_gen_subi_tl(s->T1, s->T1, 1);
+- tcg_gen_and_tl(s->T0, s->T0, s->T1);
++ tcg_gen_shl_tl(s->T1, mone, s->A0);
++ tcg_gen_movcond_tl(TCG_COND_LEU, s->T1, s->A0, bound, s->T1, zero);
++ tcg_gen_andc_tl(s->T0, s->T0, s->T1);
+
+ gen_op_update1_cc(s);
+ set_cc_op(s, CC_OP_LOGICB + ot);
+@@ -1111,6 +1113,7 @@ static void gen_BLSI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ {
+ MemOp ot = decode->op[0].ot;
+
++ tcg_gen_mov_tl(cpu_cc_src, s->T0);
+ tcg_gen_neg_tl(s->T1, s->T0);
+ tcg_gen_and_tl(s->T0, s->T0, s->T1);
+ tcg_gen_mov_tl(cpu_cc_dst, s->T0);
+@@ -1121,6 +1124,7 @@ static void gen_BLSMSK(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode
+ {
+ MemOp ot = decode->op[0].ot;
+
++ tcg_gen_mov_tl(cpu_cc_src, s->T0);
+ tcg_gen_subi_tl(s->T1, s->T0, 1);
+ tcg_gen_xor_tl(s->T0, s->T0, s->T1);
+ tcg_gen_mov_tl(cpu_cc_dst, s->T0);
+@@ -1131,6 +1135,7 @@ static void gen_BLSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ {
+ MemOp ot = decode->op[0].ot;
+
++ tcg_gen_mov_tl(cpu_cc_src, s->T0);
+ tcg_gen_subi_tl(s->T1, s->T0, 1);
+ tcg_gen_and_tl(s->T0, s->T0, s->T1);
+ tcg_gen_mov_tl(cpu_cc_dst, s->T0);
+@@ -1140,20 +1145,20 @@ static void gen_BLSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ static void gen_BZHI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ {
+ MemOp ot = decode->op[0].ot;
+- TCGv bound;
++ TCGv bound = tcg_constant_tl(ot == MO_64 ? 63 : 31);
++ TCGv zero = tcg_constant_tl(0);
++ TCGv mone = tcg_constant_tl(-1);
+
+- tcg_gen_ext8u_tl(s->T1, cpu_regs[s->vex_v]);
+- bound = tcg_constant_tl(ot == MO_64 ? 63 : 31);
++ tcg_gen_ext8u_tl(s->T1, s->T1);
+
+ /*
+ * Note that since we're using BMILG (in order to get O
+ * cleared) we need to store the inverse into C.
+ */
+- tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src, s->T1, bound);
+- tcg_gen_movcond_tl(TCG_COND_GT, s->T1, s->T1, bound, bound, s->T1);
++ tcg_gen_setcond_tl(TCG_COND_LEU, cpu_cc_src, s->T1, bound);
+
+- tcg_gen_movi_tl(s->A0, -1);
+- tcg_gen_shl_tl(s->A0, s->A0, s->T1);
++ tcg_gen_shl_tl(s->A0, mone, s->T1);
++ tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->T1, bound, s->A0, zero);
+ tcg_gen_andc_tl(s->T0, s->T0, s->A0);
+
+ gen_op_update1_cc(s);
+diff --git a/target/riscv/translate.c b/target/riscv/translate.c
+index db123da5ec..1ed4bb5ec3 100644
+--- a/target/riscv/translate.c
++++ b/target/riscv/translate.c
+@@ -1064,14 +1064,10 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
+
+ /* Check for compressed insn */
+ if (insn_len(opcode) == 2) {
+- if (!has_ext(ctx, RVC)) {
+- gen_exception_illegal(ctx);
+- } else {
+- ctx->opcode = opcode;
+- ctx->pc_succ_insn = ctx->base.pc_next + 2;
+- if (decode_insn16(ctx, opcode)) {
+- return;
+- }
++ ctx->opcode = opcode;
++ ctx->pc_succ_insn = ctx->base.pc_next + 2;
++ if (has_ext(ctx, RVC) && decode_insn16(ctx, opcode)) {
++ return;
+ }
+ } else {
+ uint32_t opcode32 = opcode;
+diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
+index 453268392b..827cee25af 100644
+--- a/target/sh4/cpu.c
++++ b/target/sh4/cpu.c
+@@ -47,7 +47,7 @@ static void superh_cpu_synchronize_from_tb(CPUState *cs,
+ SuperHCPU *cpu = SUPERH_CPU(cs);
+
+ cpu->env.pc = tb_pc(tb);
+- cpu->env.flags = tb->flags;
++ cpu->env.flags = tb->flags & TB_FLAG_ENVFLAGS_MASK;
+ }
+
+ static void superh_restore_state_to_opc(CPUState *cs,
+diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target
+index 75257f2b29..14bc013181 100644
+--- a/tests/tcg/Makefile.target
++++ b/tests/tcg/Makefile.target
+@@ -117,6 +117,8 @@ endif
+
+ %: %.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
++%: %.S
++ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
+ else
+ # For softmmu targets we include a different Makefile fragement as the
+ # build options for bare programs are usually pretty different. They
+diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target
+index 81831cafbc..bafd8c2180 100644
+--- a/tests/tcg/i386/Makefile.target
++++ b/tests/tcg/i386/Makefile.target
+@@ -14,7 +14,7 @@ config-cc.mak: Makefile
+ I386_SRCS=$(notdir $(wildcard $(I386_SRC)/*.c))
+ ALL_X86_TESTS=$(I386_SRCS:.c=)
+ SKIP_I386_TESTS=test-i386-ssse3 test-avx test-3dnow test-mmx
+-X86_64_TESTS:=$(filter test-i386-bmi2 $(SKIP_I386_TESTS), $(ALL_X86_TESTS))
++X86_64_TESTS:=$(filter test-i386-adcox test-i386-bmi2 $(SKIP_I386_TESTS), $(ALL_X86_TESTS))
+
+ test-i386-sse-exceptions: CFLAGS += -msse4.1 -mfpmath=sse
+ run-test-i386-sse-exceptions: QEMU_OPTS += -cpu max
+@@ -28,6 +28,10 @@ test-i386-bmi2: CFLAGS=-O2
+ run-test-i386-bmi2: QEMU_OPTS += -cpu max
+ run-plugin-test-i386-bmi2-%: QEMU_OPTS += -cpu max
+
++test-i386-adcox: CFLAGS=-O2
++run-test-i386-adcox: QEMU_OPTS += -cpu max
++run-plugin-test-i386-adcox-%: QEMU_OPTS += -cpu max
++
+ #
+ # hello-i386 is a barebones app
+ #
+diff --git a/tests/tcg/i386/test-i386-adcox.c b/tests/tcg/i386/test-i386-adcox.c
+new file mode 100644
+index 0000000000..16169efff8
+--- /dev/null
++++ b/tests/tcg/i386/test-i386-adcox.c
+@@ -0,0 +1,75 @@
++/* See if various BMI2 instructions give expected results */
++#include <assert.h>
++#include <stdint.h>
++#include <stdio.h>
++
++#define CC_C 1
++#define CC_O (1 << 11)
++
++#ifdef __x86_64__
++#define REG uint64_t
++#else
++#define REG uint32_t
++#endif
++
++void test_adox_adcx(uint32_t in_c, uint32_t in_o, REG adcx_operand, REG adox_operand)
++{
++ REG flags;
++ REG out_adcx, out_adox;
++
++ asm("pushf; pop %0" : "=r"(flags));
++ flags &= ~(CC_C | CC_O);
++ flags |= (in_c ? CC_C : 0);
++ flags |= (in_o ? CC_O : 0);
++
++ out_adcx = adcx_operand;
++ out_adox = adox_operand;
++ asm("push %0; popf;"
++ "adox %3, %2;"
++ "adcx %3, %1;"
++ "pushf; pop %0"
++ : "+r" (flags), "+r" (out_adcx), "+r" (out_adox)
++ : "r" ((REG)-1), "0" (flags), "1" (out_adcx), "2" (out_adox));
++
++ assert(out_adcx == in_c + adcx_operand - 1);
++ assert(out_adox == in_o + adox_operand - 1);
++ assert(!!(flags & CC_C) == (in_c || adcx_operand));
++ assert(!!(flags & CC_O) == (in_o || adox_operand));
++}
++
++void test_adcx_adox(uint32_t in_c, uint32_t in_o, REG adcx_operand, REG adox_operand)
++{
++ REG flags;
++ REG out_adcx, out_adox;
++
++ asm("pushf; pop %0" : "=r"(flags));
++ flags &= ~(CC_C | CC_O);
++ flags |= (in_c ? CC_C : 0);
++ flags |= (in_o ? CC_O : 0);
++
++ out_adcx = adcx_operand;
++ out_adox = adox_operand;
++ asm("push %0; popf;"
++ "adcx %3, %1;"
++ "adox %3, %2;"
++ "pushf; pop %0"
++ : "+r" (flags), "+r" (out_adcx), "+r" (out_adox)
++ : "r" ((REG)-1), "0" (flags), "1" (out_adcx), "2" (out_adox));
++
++ assert(out_adcx == in_c + adcx_operand - 1);
++ assert(out_adox == in_o + adox_operand - 1);
++ assert(!!(flags & CC_C) == (in_c || adcx_operand));
++ assert(!!(flags & CC_O) == (in_o || adox_operand));
++}
++
++int main(int argc, char *argv[]) {
++ /* try all combinations of input CF, input OF, CF from op1+op2, OF from op2+op1 */
++ int i;
++ for (i = 0; i <= 15; i++) {
++ printf("%d\n", i);
++ test_adcx_adox(!!(i & 1), !!(i & 2), !!(i & 4), !!(i & 8));
++ test_adox_adcx(!!(i & 1), !!(i & 2), !!(i & 4), !!(i & 8));
++ }
++ return 0;
++}
++
+diff --git a/tests/tcg/i386/test-i386-bmi2.c b/tests/tcg/i386/test-i386-bmi2.c
+index 5fadf47510..0244df7987 100644
+--- a/tests/tcg/i386/test-i386-bmi2.c
++++ b/tests/tcg/i386/test-i386-bmi2.c
+@@ -3,34 +3,40 @@
+ #include <stdint.h>
+ #include <stdio.h>
+
++#ifdef __x86_64
++typedef uint64_t reg_t;
++#else
++typedef uint32_t reg_t;
++#endif
++
+ #define insn1q(name, arg0) \
+-static inline uint64_t name##q(uint64_t arg0) \
++static inline reg_t name##q(reg_t arg0) \
+ { \
+- uint64_t result64; \
++ reg_t result64; \
+ asm volatile (#name "q %1, %0" : "=r"(result64) : "rm"(arg0)); \
+ return result64; \
+ }
+
+ #define insn1l(name, arg0) \
+-static inline uint32_t name##l(uint32_t arg0) \
++static inline reg_t name##l(reg_t arg0) \
+ { \
+- uint32_t result32; \
++ reg_t result32; \
+ asm volatile (#name "l %k1, %k0" : "=r"(result32) : "rm"(arg0)); \
+ return result32; \
+ }
+
+ #define insn2q(name, arg0, c0, arg1, c1) \
+-static inline uint64_t name##q(uint64_t arg0, uint64_t arg1) \
++static inline reg_t name##q(reg_t arg0, reg_t arg1) \
+ { \
+- uint64_t result64; \
++ reg_t result64; \
+ asm volatile (#name "q %2, %1, %0" : "=r"(result64) : c0(arg0), c1(arg1)); \
+ return result64; \
+ }
+
+ #define insn2l(name, arg0, c0, arg1, c1) \
+-static inline uint32_t name##l(uint32_t arg0, uint32_t arg1) \
++static inline reg_t name##l(reg_t arg0, reg_t arg1) \
+ { \
+- uint32_t result32; \
++ reg_t result32; \
+ asm volatile (#name "l %k2, %k1, %k0" : "=r"(result32) : c0(arg0), c1(arg1)); \
+ return result32; \
+ }
+@@ -65,130 +71,143 @@ insn1l(blsr, src)
+ int main(int argc, char *argv[]) {
+ uint64_t ehlo = 0x202020204f4c4845ull;
+ uint64_t mask = 0xa080800302020001ull;
+- uint32_t result32;
++ reg_t result;
+
+ #ifdef __x86_64
+- uint64_t result64;
+-
+ /* 64 bits */
+- result64 = andnq(mask, ehlo);
+- assert(result64 == 0x002020204d4c4844);
++ result = andnq(mask, ehlo);
++ assert(result == 0x002020204d4c4844);
++
++ result = pextq(ehlo, mask);
++ assert(result == 133);
+
+- result64 = pextq(ehlo, mask);
+- assert(result64 == 133);
++ result = pdepq(result, mask);
++ assert(result == (ehlo & mask));
+
+- result64 = pdepq(result64, mask);
+- assert(result64 == (ehlo & mask));
++ result = pextq(-1ull, mask);
++ assert(result == 511); /* mask has 9 bits set */
+
+- result64 = pextq(-1ull, mask);
+- assert(result64 == 511); /* mask has 9 bits set */
++ result = pdepq(-1ull, mask);
++ assert(result == mask);
+
+- result64 = pdepq(-1ull, mask);
+- assert(result64 == mask);
++ result = bextrq(mask, 0x3f00);
++ assert(result == (mask & ~INT64_MIN));
+
+- result64 = bextrq(mask, 0x3f00);
+- assert(result64 == (mask & ~INT64_MIN));
++ result = bextrq(mask, 0x1038);
++ assert(result == 0xa0);
+
+- result64 = bextrq(mask, 0x1038);
+- assert(result64 == 0xa0);
++ result = bextrq(mask, 0x10f8);
++ assert(result == 0);
+
+- result64 = bextrq(mask, 0x10f8);
+- assert(result64 == 0);
++ result = bextrq(0xfedcba9876543210ull, 0x7f00);
++ assert(result == 0xfedcba9876543210ull);
+
+- result64 = blsiq(0x30);
+- assert(result64 == 0x10);
++ result = blsiq(0x30);
++ assert(result == 0x10);
+
+- result64 = blsiq(0x30ull << 32);
+- assert(result64 == 0x10ull << 32);
++ result = blsiq(0x30ull << 32);
++ assert(result == 0x10ull << 32);
+
+- result64 = blsmskq(0x30);
+- assert(result64 == 0x1f);
++ result = blsmskq(0x30);
++ assert(result == 0x1f);
+
+- result64 = blsrq(0x30);
+- assert(result64 == 0x20);
++ result = blsrq(0x30);
++ assert(result == 0x20);
+
+- result64 = blsrq(0x30ull << 32);
+- assert(result64 == 0x20ull << 32);
++ result = blsrq(0x30ull << 32);
++ assert(result == 0x20ull << 32);
+
+- result64 = bzhiq(mask, 0x3f);
+- assert(result64 == (mask & ~INT64_MIN));
++ result = bzhiq(mask, 0x3f);
++ assert(result == (mask & ~INT64_MIN));
+
+- result64 = bzhiq(mask, 0x1f);
+- assert(result64 == (mask & ~(-1 << 30)));
++ result = bzhiq(mask, 0x1f);
++ assert(result == (mask & ~(-1 << 30)));
+
+- result64 = rorxq(0x2132435465768798, 8);
+- assert(result64 == 0x9821324354657687);
++ result = bzhiq(mask, 0x40);
++ assert(result == mask);
+
+- result64 = sarxq(0xffeeddccbbaa9988, 8);
+- assert(result64 == 0xffffeeddccbbaa99);
++ result = rorxq(0x2132435465768798, 8);
++ assert(result == 0x9821324354657687);
+
+- result64 = sarxq(0x77eeddccbbaa9988, 8 | 64);
+- assert(result64 == 0x0077eeddccbbaa99);
++ result = sarxq(0xffeeddccbbaa9988, 8);
++ assert(result == 0xffffeeddccbbaa99);
+
+- result64 = shrxq(0xffeeddccbbaa9988, 8);
+- assert(result64 == 0x00ffeeddccbbaa99);
++ result = sarxq(0x77eeddccbbaa9988, 8 | 64);
++ assert(result == 0x0077eeddccbbaa99);
+
+- result64 = shrxq(0x77eeddccbbaa9988, 8 | 192);
+- assert(result64 == 0x0077eeddccbbaa99);
++ result = shrxq(0xffeeddccbbaa9988, 8);
++ assert(result == 0x00ffeeddccbbaa99);
+
+- result64 = shlxq(0xffeeddccbbaa9988, 8);
+- assert(result64 == 0xeeddccbbaa998800);
++ result = shrxq(0x77eeddccbbaa9988, 8 | 192);
++ assert(result == 0x0077eeddccbbaa99);
++
++ result = shlxq(0xffeeddccbbaa9988, 8);
++ assert(result == 0xeeddccbbaa998800);
+ #endif
+
+ /* 32 bits */
+- result32 = andnl(mask, ehlo);
+- assert(result32 == 0x04d4c4844);
++ result = andnl(mask, ehlo);
++ assert(result == 0x04d4c4844);
++
++ result = pextl((uint32_t) ehlo, mask);
++ assert(result == 5);
++
++ result = pdepl(result, mask);
++ assert(result == (uint32_t)(ehlo & mask));
++
++ result = pextl(-1u, mask);
++ assert(result == 7); /* mask has 3 bits set */
+
+- result32 = pextl((uint32_t) ehlo, mask);
+- assert(result32 == 5);
++ result = pdepl(-1u, mask);
++ assert(result == (uint32_t)mask);
+
+- result32 = pdepl(result32, mask);
+- assert(result32 == (uint32_t)(ehlo & mask));
++ result = bextrl(mask, 0x1f00);
++ assert(result == (mask & ~INT32_MIN));
+
+- result32 = pextl(-1u, mask);
+- assert(result32 == 7); /* mask has 3 bits set */
++ result = bextrl(ehlo, 0x1018);
++ assert(result == 0x4f);
+
+- result32 = pdepl(-1u, mask);
+- assert(result32 == (uint32_t)mask);
++ result = bextrl(mask, 0x1038);
++ assert(result == 0);
+
+- result32 = bextrl(mask, 0x1f00);
+- assert(result32 == (mask & ~INT32_MIN));
++ result = bextrl((reg_t)0x8f635a775ad3b9b4ull, 0x3018);
++ assert(result == 0x5a);
+
+- result32 = bextrl(ehlo, 0x1018);
+- assert(result32 == 0x4f);
++ result = bextrl((reg_t)0xfedcba9876543210ull, 0x7f00);
++ assert(result == 0x76543210u);
+
+- result32 = bextrl(mask, 0x1038);
+- assert(result32 == 0);
++ result = bextrl(-1, 0);
++ assert(result == 0);
+
+- result32 = blsil(0xffff);
+- assert(result32 == 1);
++ result = blsil(0xffff);
++ assert(result == 1);
+
+- result32 = blsmskl(0x300);
+- assert(result32 == 0x1ff);
++ result = blsmskl(0x300);
++ assert(result == 0x1ff);
+
+- result32 = blsrl(0xffc);
+- assert(result32 == 0xff8);
++ result = blsrl(0xffc);
++ assert(result == 0xff8);
+
+- result32 = bzhil(mask, 0xf);
+- assert(result32 == 1);
++ result = bzhil(mask, 0xf);
++ assert(result == 1);
+
+- result32 = rorxl(0x65768798, 8);
+- assert(result32 == 0x98657687);
++ result = rorxl(0x65768798, 8);
++ assert(result == 0x98657687);
+
+- result32 = sarxl(0xffeeddcc, 8);
+- assert(result32 == 0xffffeedd);
++ result = sarxl(0xffeeddcc, 8);
++ assert(result == 0xffffeedd);
+
+- result32 = sarxl(0x77eeddcc, 8 | 32);
+- assert(result32 == 0x0077eedd);
++ result = sarxl(0x77eeddcc, 8 | 32);
++ assert(result == 0x0077eedd);
+
+- result32 = shrxl(0xffeeddcc, 8);
+- assert(result32 == 0x00ffeedd);
++ result = shrxl(0xffeeddcc, 8);
++ assert(result == 0x00ffeedd);
+
+- result32 = shrxl(0x77eeddcc, 8 | 128);
+- assert(result32 == 0x0077eedd);
++ result = shrxl(0x77eeddcc, 8 | 128);
++ assert(result == 0x0077eedd);
+
+- result32 = shlxl(0xffeeddcc, 8);
+- assert(result32 == 0xeeddcc00);
++ result = shlxl(0xffeeddcc, 8);
++ assert(result == 0xeeddcc00);
+
+ return 0;
+ }
+diff --git a/tests/tcg/multiarch/linux/linux-test.c b/tests/tcg/multiarch/linux/linux-test.c
+index 5a2a4f2258..64f57cb287 100644
+--- a/tests/tcg/multiarch/linux/linux-test.c
++++ b/tests/tcg/multiarch/linux/linux-test.c
+@@ -354,13 +354,17 @@ static void test_pipe(void)
+ if (FD_ISSET(fds[0], &rfds)) {
+ chk_error(read(fds[0], &ch, 1));
+ rcount++;
+- if (rcount >= WCOUNT_MAX)
++ if (rcount >= WCOUNT_MAX) {
+ break;
++ }
+ }
+ if (FD_ISSET(fds[1], &wfds)) {
+ ch = 'a';
+ chk_error(write(fds[1], &ch, 1));
+ wcount++;
++ if (wcount >= WCOUNT_MAX) {
++ break;
++ }
+ }
+ }
+ }
+diff --git a/tests/tcg/riscv64/Makefile.target b/tests/tcg/riscv64/Makefile.target
+index b5b89dfb0e..cc3ed65ffd 100644
+--- a/tests/tcg/riscv64/Makefile.target
++++ b/tests/tcg/riscv64/Makefile.target
+@@ -4,3 +4,9 @@
+ VPATH += $(SRC_PATH)/tests/tcg/riscv64
+ TESTS += test-div
+ TESTS += noexec
++
++# Disable compressed instructions for test-noc
++TESTS += test-noc
++test-noc: LDFLAGS = -nostdlib -static
++run-test-noc: QEMU_OPTS += -cpu rv64,c=false
++run-plugin-test-noc-%: QEMU_OPTS += -cpu rv64,c=false
+diff --git a/tests/tcg/riscv64/test-noc.S b/tests/tcg/riscv64/test-noc.S
+new file mode 100644
+index 0000000000..e29d60c8b3
+--- /dev/null
++++ b/tests/tcg/riscv64/test-noc.S
+@@ -0,0 +1,32 @@
++#include <asm/unistd.h>
++
++ .text
++ .globl _start
++_start:
++ .option norvc
++ li a0, 4 /* SIGILL */
++ la a1, sa
++ li a2, 0
++ li a3, 8
++ li a7, __NR_rt_sigaction
++ scall
++
++ .option rvc
++ li a0, 1
++ j exit
++ .option norvc
++
++pass:
++ li a0, 0
++exit:
++ li a7, __NR_exit
++ scall
++
++ .data
++ /* struct kernel_sigaction sa = { .sa_handler = pass }; */
++ .type sa, @object
++ .size sa, 32
++sa:
++ .dword pass
++ .zero 24
++