diff options
92 files changed, 849 insertions, 613 deletions
diff --git a/Kconfig.host b/Kconfig.host index add5b179f7..aec95365ff 100644 --- a/Kconfig.host +++ b/Kconfig.host @@ -31,3 +31,6 @@ config XEN config VIRTFS bool + +config PVRDMA + bool diff --git a/MAINTAINERS b/MAINTAINERS index 85d7d764e5..56139ac8ab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1813,7 +1813,8 @@ F: qom/cpu.c F: include/qom/cpu.h Device Tree -M: Alexander Graf <agraf@suse.de> +M: Alistair Francis <alistair.francis@wdc.com> +R: David Gibson <david@gibson.dropbear.id.au> S: Maintained F: device_tree.c F: include/sysemu/device_tree.h @@ -2178,7 +2179,7 @@ F: include/migration/failover.h F: docs/COLO-FT.txt COLO Proxy -M: Zhang Chen <zhangckid@gmail.com> +M: Zhang Chen <chen.zhang@intel.com> M: Li Zhijian <lizhijian@cn.fujitsu.com> S: Supported F: docs/colo-proxy.txt @@ -331,10 +331,10 @@ SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(filter %-softmmu, $(TAR SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %.d, $(SUBDIR_DEVICES_MAK)) ifeq ($(SUBDIR_DEVICES_MAK),) -config-all-devices.mak: +config-all-devices.mak: config-host.mak $(call quiet-command,echo '# no devices' > $@,"GEN","$@") else -config-all-devices.mak: $(SUBDIR_DEVICES_MAK) +config-all-devices.mak: $(SUBDIR_DEVICES_MAK) config-host.mak $(call quiet-command, sed -n \ 's|^\([^=]*\)=\(.*\)$$|\1:=$$(findstring y,$$(\1)\2)|p' \ $(SUBDIR_DEVICES_MAK) | sort -u > $@, \ @@ -356,7 +356,8 @@ MINIKCONF_ARGS = \ CONFIG_X11=$(CONFIG_X11) \ CONFIG_VHOST_USER=$(CONFIG_VHOST_USER) \ CONFIG_VIRTFS=$(CONFIG_VIRTFS) \ - CONFIG_LINUX=$(CONFIG_LINUX) + CONFIG_LINUX=$(CONFIG_LINUX) \ + CONFIG_PVRDMA=$(CONFIG_PVRDMA) MINIKCONF_INPUTS = $(SRC_PATH)/Kconfig.host $(SRC_PATH)/hw/Kconfig MINIKCONF = $(PYTHON) $(SRC_PATH)/scripts/minikconf.py \ @@ -1 +1 @@ -3.1.90 +3.1.91 diff --git a/block/blkdebug.c b/block/blkdebug.c index 1ea835c2b9..efd9441625 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -401,7 +401,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | (BDRV_REQ_FUA & bs->file->bs->supported_write_flags); bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | - ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) & + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & bs->file->bs->supported_zero_flags); ret = -EINVAL; diff --git a/block/copy-on-read.c b/block/copy-on-read.c index d670fec42b..53972b1da3 100644 --- a/block/copy-on-read.c +++ b/block/copy-on-read.c @@ -34,12 +34,11 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags, } bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | - (BDRV_REQ_FUA & - bs->file->bs->supported_write_flags); + (BDRV_REQ_FUA & bs->file->bs->supported_write_flags); bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | - ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) & - bs->file->bs->supported_zero_flags); + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & + bs->file->bs->supported_zero_flags); return 0; } diff --git a/block/file-posix.c b/block/file-posix.c index d102f3b222..db4cccbe51 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -652,7 +652,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, } #endif - bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP; + bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK; ret = 0; fail: if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) { @@ -1500,14 +1500,19 @@ static ssize_t handle_aiocb_write_zeroes_block(RawPosixAIOData *aiocb) } #ifdef BLKZEROOUT - do { - uint64_t range[2] = { aiocb->aio_offset, aiocb->aio_nbytes }; - if (ioctl(aiocb->aio_fildes, BLKZEROOUT, range) == 0) { - return 0; - } - } while (errno == EINTR); + /* The BLKZEROOUT implementation in the kernel doesn't set + * BLKDEV_ZERO_NOFALLBACK, so we can't call this if we have to avoid slow + * fallbacks. */ + if (!(aiocb->aio_type & QEMU_AIO_NO_FALLBACK)) { + do { + uint64_t range[2] = { aiocb->aio_offset, aiocb->aio_nbytes }; + if (ioctl(aiocb->aio_fildes, BLKZEROOUT, range) == 0) { + return 0; + } + } while (errno == EINTR); - ret = translate_err(-errno); + ret = translate_err(-errno); + } #endif if (ret == -ENOTSUP) { @@ -2659,6 +2664,9 @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes, if (blkdev) { acb.aio_type |= QEMU_AIO_BLKDEV; } + if (flags & BDRV_REQ_NO_FALLBACK) { + acb.aio_type |= QEMU_AIO_NO_FALLBACK; + } if (flags & BDRV_REQ_MAY_UNMAP) { acb.aio_type |= QEMU_AIO_DISCARD; diff --git a/block/io.c b/block/io.c index 2ba603c7bc..dfc153b8d8 100644 --- a/block/io.c +++ b/block/io.c @@ -909,8 +909,6 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags) } ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL, NULL); if (ret < 0) { - error_report("error getting block status at offset %" PRId64 ": %s", - offset, strerror(-ret)); return ret; } if (ret & BDRV_BLOCK_ZERO) { @@ -919,8 +917,6 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags) } ret = bdrv_pwrite_zeroes(child, offset, bytes, flags); if (ret < 0) { - error_report("error writing zeroes at offset %" PRId64 ": %s", - offset, strerror(-ret)); return ret; } offset += bytes; @@ -1019,6 +1015,7 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, unsigned int nb_sectors; assert(!(flags & ~BDRV_REQ_MASK)); + assert(!(flags & BDRV_REQ_NO_FALLBACK)); if (!drv) { return -ENOMEDIUM; @@ -1065,6 +1062,7 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, int ret; assert(!(flags & ~BDRV_REQ_MASK)); + assert(!(flags & BDRV_REQ_NO_FALLBACK)); if (!drv) { return -ENOMEDIUM; @@ -1471,6 +1469,10 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, return -ENOMEDIUM; } + if ((flags & ~bs->supported_zero_flags) & BDRV_REQ_NO_FALLBACK) { + return -ENOTSUP; + } + assert(alignment % bs->bl.request_alignment == 0); head = offset % alignment; tail = (offset + bytes) % alignment; @@ -1514,7 +1516,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, assert(!bs->supported_zero_flags); } - if (ret == -ENOTSUP) { + if (ret == -ENOTSUP && !(flags & BDRV_REQ_NO_FALLBACK)) { /* Fall back to bounce buffer if write zeroes is unsupported */ BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE; @@ -2953,6 +2955,10 @@ static int coroutine_fn bdrv_co_copy_range_internal( BdrvTrackedRequest req; int ret; + /* TODO We can support BDRV_REQ_NO_FALLBACK here */ + assert(!(read_flags & BDRV_REQ_NO_FALLBACK)); + assert(!(write_flags & BDRV_REQ_NO_FALLBACK)); + if (!dst || !dst->bs) { return -ENOMEDIUM; } diff --git a/block/mirror.c b/block/mirror.c index eb9a4cdf56..ff15cfb197 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1548,7 +1548,8 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs, } mirror_top_bs->total_sectors = bs->total_sectors; mirror_top_bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED; - mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED; + mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | + BDRV_REQ_NO_FALLBACK; bs_opaque = g_new0(MirrorBDSOpaque, 1); mirror_top_bs->opaque = bs_opaque; bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs)); diff --git a/block/raw-format.c b/block/raw-format.c index cec29986cc..385cdc2490 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -434,7 +434,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | (BDRV_REQ_FUA & bs->file->bs->supported_write_flags); bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | - ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) & + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & bs->file->bs->supported_zero_flags); if (bs->probed && !bdrv_is_read_only(bs)) { diff --git a/default-configs/mips-softmmu-common.mak b/default-configs/mips-softmmu-common.mak index 0795d522db..8e54a74b7a 100644 --- a/default-configs/mips-softmmu-common.mak +++ b/default-configs/mips-softmmu-common.mak @@ -35,6 +35,7 @@ CONFIG_MIPS_CPS=y CONFIG_MIPS_ITU=y CONFIG_R4K=y CONFIG_MALTA=y +CONFIG_PCNET_PCI=y CONFIG_MIPSSIM=y CONFIG_ACPI_SMBUS=y CONFIG_SMBUS_EEPROM=y diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak index 8b255efc54..a67c9517a2 100644 --- a/default-configs/mips64el-softmmu.mak +++ b/default-configs/mips64el-softmmu.mak @@ -6,6 +6,8 @@ CONFIG_RC4030=y CONFIG_DP8393X=y CONFIG_DS1225Y=y CONFIG_FULONG=y +CONFIG_ATI_VGA=y +CONFIG_RTL8139_PCI=y CONFIG_JAZZ=y CONFIG_G364FB=y CONFIG_JAZZ_LED=y @@ -1692,9 +1692,10 @@ static int find_max_supported_pagesize(Object *obj, void *opaque) long *hpsize_min = opaque; if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) { - long hpsize = host_memory_backend_pagesize(MEMORY_BACKEND(obj)); + HostMemoryBackend *backend = MEMORY_BACKEND(obj); + long hpsize = host_memory_backend_pagesize(backend); - if (hpsize < *hpsize_min) { + if (host_memory_backend_is_mapped(backend) && (hpsize < *hpsize_min)) { *hpsize_min = hpsize; } } @@ -1152,6 +1152,7 @@ static int gdb_handle_vcont(GDBState *s, const char *p) uint32_t pid, tid; GDBProcess *process; CPUState *cpu; + GDBThreadIdKind kind; #ifdef CONFIG_USER_ONLY int max_cpus = 1; /* global variable max_cpus exists only in system mode */ @@ -1194,12 +1195,21 @@ static int gdb_handle_vcont(GDBState *s, const char *p) goto out; } - if (*p++ != ':') { + if (*p == '\0' || *p == ';') { + /* + * No thread specifier, action is on "all threads". The + * specification is unclear regarding the process to act on. We + * choose all processes. + */ + kind = GDB_ALL_PROCESSES; + } else if (*p++ == ':') { + kind = read_thread_id(p, &p, &pid, &tid); + } else { res = -ENOTSUP; goto out; } - switch (read_thread_id(p, &p, &pid, &tid)) { + switch (kind) { case GDB_READ_THREAD_ERR: res = -EINVAL; goto out; @@ -433,17 +433,17 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) MigrationParameter_str(MIGRATION_PARAMETER_BLOCK_INCREMENTAL), params->block_incremental ? "on" : "off"); monitor_printf(mon, "%s: %u\n", - MigrationParameter_str(MIGRATION_PARAMETER_X_MULTIFD_CHANNELS), - params->x_multifd_channels); - monitor_printf(mon, "%s: %u\n", - MigrationParameter_str(MIGRATION_PARAMETER_X_MULTIFD_PAGE_COUNT), - params->x_multifd_page_count); + MigrationParameter_str(MIGRATION_PARAMETER_MULTIFD_CHANNELS), + params->multifd_channels); monitor_printf(mon, "%s: %" PRIu64 "\n", MigrationParameter_str(MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE), params->xbzrle_cache_size); monitor_printf(mon, "%s: %" PRIu64 "\n", MigrationParameter_str(MIGRATION_PARAMETER_MAX_POSTCOPY_BANDWIDTH), params->max_postcopy_bandwidth); + monitor_printf(mon, " %s: '%s'\n", + MigrationParameter_str(MIGRATION_PARAMETER_TLS_AUTHZ), + params->has_tls_authz ? params->tls_authz : ""); } qapi_free_MigrationParameters(params); @@ -1786,6 +1786,12 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) p->tls_hostname->type = QTYPE_QSTRING; visit_type_str(v, param, &p->tls_hostname->u.s, &err); break; + case MIGRATION_PARAMETER_TLS_AUTHZ: + p->has_tls_authz = true; + p->tls_authz = g_new0(StrOrNull, 1); + p->tls_authz->type = QTYPE_QSTRING; + visit_type_str(v, param, &p->tls_authz->u.s, &err); + break; case MIGRATION_PARAMETER_MAX_BANDWIDTH: p->has_max_bandwidth = true; /* @@ -1812,13 +1818,9 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) p->has_block_incremental = true; visit_type_bool(v, param, &p->block_incremental, &err); break; - case MIGRATION_PARAMETER_X_MULTIFD_CHANNELS: - p->has_x_multifd_channels = true; - visit_type_int(v, param, &p->x_multifd_channels, &err); - break; - case MIGRATION_PARAMETER_X_MULTIFD_PAGE_COUNT: - p->has_x_multifd_page_count = true; - visit_type_int(v, param, &p->x_multifd_page_count, &err); + case MIGRATION_PARAMETER_MULTIFD_CHANNELS: + p->has_multifd_channels = true; + visit_type_int(v, param, &p->multifd_channels, &err); break; case MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE: p->has_xbzrle_cache_size = true; diff --git a/hw/Kconfig b/hw/Kconfig index d5ecd02070..88b9f15007 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -26,6 +26,7 @@ source pci-bridge/Kconfig source pci-host/Kconfig source pcmcia/Kconfig source pci/Kconfig +source rdma/Kconfig source scsi/Kconfig source sd/Kconfig source smbios/Kconfig diff --git a/hw/alpha/Kconfig b/hw/alpha/Kconfig index 22cefd9577..15c59ff264 100644 --- a/hw/alpha/Kconfig +++ b/hw/alpha/Kconfig @@ -2,6 +2,7 @@ config DP264 bool imply PCI_DEVICES imply TEST_DEVICES + imply E1000_PCI select I82374 select I8254 select I8259 diff --git a/hw/block/block.c b/hw/block/block.c index cf0eb826f1..bf56c7612b 100644 --- a/hw/block/block.c +++ b/hw/block/block.c @@ -13,7 +13,53 @@ #include "hw/block/block.h" #include "qapi/error.h" #include "qapi/qapi-types-block.h" -#include "qemu/error-report.h" + +/* + * Read the entire contents of @blk into @buf. + * @blk's contents must be @size bytes, and @size must be at most + * BDRV_REQUEST_MAX_BYTES. + * On success, return true. + * On failure, store an error through @errp and return false. + * Note that the error messages do not identify the block backend. + * TODO Since callers don't either, this can result in confusing + * errors. + * This function not intended for actual block devices, which read on + * demand. It's for things like memory devices that (ab)use a block + * backend to provide persistence. + */ +bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size, + Error **errp) +{ + int64_t blk_len; + int ret; + + blk_len = blk_getlength(blk); + if (blk_len < 0) { + error_setg_errno(errp, -blk_len, + "can't get size of block backend"); + return false; + } + if (blk_len != size) { + error_setg(errp, "device requires %" HWADDR_PRIu " bytes, " + "block backend provides %" PRIu64 " bytes", + size, blk_len); + return false; + } + + /* + * We could loop for @size > BDRV_REQUEST_MAX_BYTES, but if we + * ever get to the point we want to read *gigabytes* here, we + * should probably rework the device to be more like an actual + * block device and read only on demand. + */ + assert(size <= BDRV_REQUEST_MAX_BYTES); + ret = blk_pread(blk, 0, buf, size); + if (ret < 0) { + error_setg_errno(errp, -ret, "can't read block backend"); + return false; + } + return true; +} void blkconf_blocksizes(BlockConf *conf) { diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 125f70b8e4..16dfae14b8 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -38,6 +38,7 @@ #include "qemu/osdep.h" #include "hw/hw.h" +#include "hw/block/block.h" #include "hw/block/flash.h" #include "sysemu/block-backend.h" #include "qapi/error.h" @@ -730,13 +731,6 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) } device_len = sector_len_per_device * blocks_per_device; - /* XXX: to be fixed */ -#if 0 - if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) && - total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024)) - return NULL; -#endif - memory_region_init_rom_device( &pfl->mem, OBJECT(dev), &pflash_cfi01_ops, @@ -763,12 +757,9 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) } if (pfl->blk) { - /* read the initial flash content */ - ret = blk_pread(pfl->blk, 0, pfl->storage, total_len); - - if (ret < 0) { + if (!blk_check_size_and_read_all(pfl->blk, pfl->storage, total_len, + errp)) { vmstate_unregister_ram(&pfl->mem, DEVICE(pfl)); - error_setg(errp, "failed to read the initial flash content"); return; } } diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index c9db430611..f2c6201f81 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -37,6 +37,7 @@ #include "qemu/osdep.h" #include "hw/hw.h" +#include "hw/block/block.h" #include "hw/block/flash.h" #include "qapi/error.h" #include "qemu/timer.h" @@ -550,12 +551,6 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) } chip_len = pfl->sector_len * pfl->nb_blocs; - /* XXX: to be fixed */ -#if 0 - if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) && - total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024)) - return NULL; -#endif memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), pfl->be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, @@ -581,11 +576,9 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) } if (pfl->blk) { - /* read the initial flash content */ - ret = blk_pread(pfl->blk, 0, pfl->storage, chip_len); - if (ret < 0) { + if (!blk_check_size_and_read_all(pfl->blk, pfl->storage, chip_len, + errp)) { vmstate_unregister_ram(&pfl->orig_mem, DEVICE(pfl)); - error_setg(errp, "failed to read the initial flash content"); return; } } diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index 70fc2455e8..9c722b9b95 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -771,7 +771,7 @@ static XenBlockDrive *xen_block_drive_create(const char *id, QDict *cache_qdict = qdict_new(); qdict_put_bool(cache_qdict, "direct", true); - qdict_put_obj(file_layer, "cache", QOBJECT(cache_qdict)); + qdict_put(file_layer, "cache", cache_qdict); qdict_put_str(file_layer, "aio", "native"); } @@ -796,7 +796,7 @@ static XenBlockDrive *xen_block_drive_create(const char *id, qdict_put_str(driver_layer, "driver", driver); g_free(driver); - qdict_put_obj(driver_layer, "file", QOBJECT(file_layer)); + qdict_put(driver_layer, "file", file_layer); g_assert(!drive->node_name); drive->node_name = xen_block_blockdev_add(drive->id, driver_layer, diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs index c4947d7ae7..cf086e7114 100644 --- a/hw/char/Makefile.objs +++ b/hw/char/Makefile.objs @@ -2,7 +2,7 @@ common-obj-$(CONFIG_IPACK) += ipoctal232.o common-obj-$(CONFIG_ESCC) += escc.o common-obj-$(CONFIG_NRF51_SOC) += nrf51_uart.o common-obj-$(CONFIG_PARALLEL) += parallel.o -common-obj-$(CONFIG_PARALLEL) += parallel-isa.o +common-obj-$(CONFIG_ISA_BUS) += parallel-isa.o common-obj-$(CONFIG_PL011) += pl011.o common-obj-$(CONFIG_SERIAL) += serial.o common-obj-$(CONFIG_SERIAL_ISA) += serial-isa.o diff --git a/hw/char/parallel-isa.c b/hw/char/parallel-isa.c index 639e179585..a043832e72 100644 --- a/hw/char/parallel-isa.c +++ b/hw/char/parallel-isa.c @@ -1,6 +1,9 @@ /* * QEMU Parallel PORT (ISA bus helpers) * + * These functions reside in a separate file since they also might be + * required for linking when compiling QEMU without CONFIG_PARALLEL. + * * Copyright (c) 2003 Fabrice Bellard * * SPDX-License-Identifier: MIT diff --git a/hw/display/Kconfig b/hw/display/Kconfig index 86c1d544c5..72be57a403 100644 --- a/hw/display/Kconfig +++ b/hw/display/Kconfig @@ -100,7 +100,7 @@ config VIRTIO_GPU config VIRTIO_VGA bool - default y if PCI_DEVICES + # defaults to "N", enabled by specific boards depends on VIRTIO_PCI select VGA diff --git a/hw/display/ati.c b/hw/display/ati.c index 8322f52aff..db409be3c9 100644 --- a/hw/display/ati.c +++ b/hw/display/ati.c @@ -235,12 +235,9 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size) case MM_DATA ... MM_DATA + 3: /* indexed access to regs or memory */ if (s->regs.mm_index & BIT(31)) { - if (s->regs.mm_index <= s->vga.vram_size - size) { - int i = size - 1; - while (i >= 0) { - val <<= 8; - val |= s->vga.vram_ptr[s->regs.mm_index + i--]; - } + uint32_t idx = s->regs.mm_index & ~BIT(31); + if (idx <= s->vga.vram_size - size) { + val = ldn_le_p(s->vga.vram_ptr + idx, size); } } else { val = ati_mm_read(s, s->regs.mm_index + addr - MM_DATA, size); @@ -434,12 +431,9 @@ static void ati_mm_write(void *opaque, hwaddr addr, case MM_DATA ... MM_DATA + 3: /* indexed access to regs or memory */ if (s->regs.mm_index & BIT(31)) { - if (s->regs.mm_index <= s->vga.vram_size - size) { - int i = 0; - while (i < size) { - s->vga.vram_ptr[s->regs.mm_index + i] = data & 0xff; - data >>= 8; - } + uint32_t idx = s->regs.mm_index & ~BIT(31); + if (idx <= s->vga.vram_size - size) { + stn_le_p(s->vga.vram_ptr + idx, size, data); } } else { ati_mm_write(s, s->regs.mm_index + addr - MM_DATA, data, size); diff --git a/hw/hppa/Kconfig b/hw/hppa/Kconfig index 2d9b072c21..6e5d74a825 100644 --- a/hw/hppa/Kconfig +++ b/hw/hppa/Kconfig @@ -1,6 +1,8 @@ config DINO bool imply PCI_DEVICES + imply E1000_PCI + imply VIRTIO_VGA select PCI select SERIAL select ISA_BUS diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig index 78fd70396a..a6aed7c131 100644 --- a/hw/i386/Kconfig +++ b/hw/i386/Kconfig @@ -9,6 +9,7 @@ config PC imply ISA_IPMI_KCS imply ISA_IPMI_BT imply ISA_DEBUG + imply PARALLEL imply PCI_DEVICES imply PVPANIC imply QXL @@ -17,16 +18,15 @@ config PC imply TEST_DEVICES imply TPM_CRB imply TPM_TIS + imply VGA_PCI + imply VIRTIO_VGA select FDC select I8259 select I8254 select PCKBD select PCSPK - select I82374 select I8257 select MC146818RTC - # Needed by the board code: - select PARALLEL # For ACPI builder: select SERIAL_ISA select ACPI_VMGENID @@ -49,6 +49,7 @@ config PC_ACPI config I440FX bool + imply E1000_PCI select PC_PCI select PC_ACPI select ACPI_SMBUS @@ -74,6 +75,7 @@ config Q35 bool imply VTD imply AMD_IOMMU + imply E1000E_PCI_EXPRESS select PC_PCI select PC_ACPI select PCI_EXPRESS_Q35 diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index b90de6c664..055a1e865d 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -1485,11 +1485,11 @@ static bool vtd_switch_address_space(VTDAddressSpace *as) /* Turn off first then on the other */ if (use_iommu) { - memory_region_set_enabled(&as->sys_alias, false); + memory_region_set_enabled(&as->nodmar, false); memory_region_set_enabled(MEMORY_REGION(&as->iommu), true); } else { memory_region_set_enabled(MEMORY_REGION(&as->iommu), false); - memory_region_set_enabled(&as->sys_alias, true); + memory_region_set_enabled(&as->nodmar, true); } if (take_bql) { @@ -3286,7 +3286,8 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn) vtd_dev_as = vtd_bus->dev_as[devfn]; if (!vtd_dev_as) { - snprintf(name, sizeof(name), "intel_iommu_devfn_%d", devfn); + snprintf(name, sizeof(name), "vtd-%02x.%x", PCI_SLOT(devfn), + PCI_FUNC(devfn)); vtd_bus->dev_as[devfn] = vtd_dev_as = g_malloc0(sizeof(VTDAddressSpace)); vtd_dev_as->bus = bus; @@ -3295,44 +3296,53 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn) vtd_dev_as->context_cache_entry.context_cache_gen = 0; vtd_dev_as->iova_tree = iova_tree_new(); + memory_region_init(&vtd_dev_as->root, OBJECT(s), name, UINT64_MAX); + address_space_init(&vtd_dev_as->as, &vtd_dev_as->root, "vtd-root"); + /* - * Memory region relationships looks like (Address range shows - * only lower 32 bits to make it short in length...): - * - * |-----------------+-------------------+----------| - * | Name | Address range | Priority | - * |-----------------+-------------------+----------+ - * | vtd_root | 00000000-ffffffff | 0 | - * | intel_iommu | 00000000-ffffffff | 1 | - * | vtd_sys_alias | 00000000-ffffffff | 1 | - * | intel_iommu_ir | fee00000-feefffff | 64 | - * |-----------------+-------------------+----------| + * Build the DMAR-disabled container with aliases to the + * shared MRs. Note that aliasing to a shared memory region + * could help the memory API to detect same FlatViews so we + * can have devices to share the same FlatView when DMAR is + * disabled (either by not providing "intel_iommu=on" or with + * "iommu=pt"). It will greatly reduce the total number of + * FlatViews of the system hence VM runs faster. + */ + memory_region_init_alias(&vtd_dev_as->nodmar, OBJECT(s), + "vtd-nodmar", &s->mr_nodmar, 0, + memory_region_size(&s->mr_nodmar)); + + /* + * Build the per-device DMAR-enabled container. * - * We enable/disable DMAR by switching enablement for - * vtd_sys_alias and intel_iommu regions. IR region is always - * enabled. + * TODO: currently we have per-device IOMMU memory region only + * because we have per-device IOMMU notifiers for devices. If + * one day we can abstract the IOMMU notifiers out of the + * memory regions then we can also share the same memory + * region here just like what we've done above with the nodmar + * region. */ + strcat(name, "-dmar"); memory_region_init_iommu(&vtd_dev_as->iommu, sizeof(vtd_dev_as->iommu), TYPE_INTEL_IOMMU_MEMORY_REGION, OBJECT(s), - "intel_iommu_dmar", - UINT64_MAX); - memory_region_init_alias(&vtd_dev_as->sys_alias, OBJECT(s), - "vtd_sys_alias", get_system_memory(), - 0, memory_region_size(get_system_memory())); - memory_region_init_io(&vtd_dev_as->iommu_ir, OBJECT(s), - &vtd_mem_ir_ops, s, "intel_iommu_ir", - VTD_INTERRUPT_ADDR_SIZE); - memory_region_init(&vtd_dev_as->root, OBJECT(s), - "vtd_root", UINT64_MAX); - memory_region_add_subregion_overlap(&vtd_dev_as->root, + name, UINT64_MAX); + memory_region_init_alias(&vtd_dev_as->iommu_ir, OBJECT(s), "vtd-ir", + &s->mr_ir, 0, memory_region_size(&s->mr_ir)); + memory_region_add_subregion_overlap(MEMORY_REGION(&vtd_dev_as->iommu), VTD_INTERRUPT_ADDR_FIRST, - &vtd_dev_as->iommu_ir, 64); - address_space_init(&vtd_dev_as->as, &vtd_dev_as->root, name); - memory_region_add_subregion_overlap(&vtd_dev_as->root, 0, - &vtd_dev_as->sys_alias, 1); + &vtd_dev_as->iommu_ir, 1); + + /* + * Hook both the containers under the root container, we + * switch between DMAR & noDMAR by enable/disable + * corresponding sub-containers + */ memory_region_add_subregion_overlap(&vtd_dev_as->root, 0, MEMORY_REGION(&vtd_dev_as->iommu), - 1); + 0); + memory_region_add_subregion_overlap(&vtd_dev_as->root, 0, + &vtd_dev_as->nodmar, 0); + vtd_switch_address_space(vtd_dev_as); } return vtd_dev_as; @@ -3676,6 +3686,21 @@ static void vtd_realize(DeviceState *dev, Error **errp) memset(s->vtd_as_by_bus_num, 0, sizeof(s->vtd_as_by_bus_num)); memory_region_init_io(&s->csrmem, OBJECT(s), &vtd_mem_ops, s, "intel_iommu", DMAR_REG_SIZE); + + /* Create the shared memory regions by all devices */ + memory_region_init(&s->mr_nodmar, OBJECT(s), "vtd-nodmar", + UINT64_MAX); + memory_region_init_io(&s->mr_ir, OBJECT(s), &vtd_mem_ir_ops, + s, "vtd-ir", VTD_INTERRUPT_ADDR_SIZE); + memory_region_init_alias(&s->mr_sys_alias, OBJECT(s), + "vtd-sys-alias", get_system_memory(), 0, + memory_region_size(get_system_memory())); + memory_region_add_subregion_overlap(&s->mr_nodmar, 0, + &s->mr_sys_alias, 0); + memory_region_add_subregion_overlap(&s->mr_nodmar, + VTD_INTERRUPT_ADDR_FIRST, + &s->mr_ir, 1); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->csrmem); /* No corresponding destroy */ s->iotlb = g_hash_table_new_full(vtd_uint64_hash, vtd_uint64_equal, diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index de10a6bcbf..5347f8412c 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -12,12 +12,15 @@ config IOAPIC config ARM_GIC bool + select MSI_NONBROKEN config OPENPIC bool + select MSI_NONBROKEN config APIC bool + select MSI_NONBROKEN config ARM_GIC_KVM bool diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig index 57e09a0cb8..6db0d7970c 100644 --- a/hw/isa/Kconfig +++ b/hw/isa/Kconfig @@ -11,6 +11,7 @@ config I82378 select I8254 select I82374 select MC146818RTC + select PCSPK config PC87312 bool @@ -29,6 +30,7 @@ config PIIX4 # For historical reasons, SuperIO devices are created in the board # for PIIX4. select ISA_BUS + select USB_UHCI config VT82C686 bool diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 2c60be99bc..5f67d0d6d9 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -34,7 +34,7 @@ config PCI_TESTDEV config EDU bool default y if TEST_DEVICES - depends on PCI + depends on PCI && MSI_NONBROKEN config PCA9552 bool @@ -67,7 +67,7 @@ config MACIO config IVSHMEM_DEVICE bool default y if PCI_DEVICES - depends on PCI && LINUX && IVSHMEM + depends on PCI && LINUX && IVSHMEM && MSI_NONBROKEN config ECCMEMCTL bool diff --git a/hw/net/Kconfig b/hw/net/Kconfig index c00ec03cd1..7d7bbc5d7c 100644 --- a/hw/net/Kconfig +++ b/hw/net/Kconfig @@ -28,7 +28,7 @@ config E1000_PCI config E1000E_PCI_EXPRESS bool default y if PCI_DEVICES - depends on PCI_EXPRESS + depends on PCI_EXPRESS && MSI_NONBROKEN config RTL8139_PCI bool @@ -107,7 +107,7 @@ config ETSEC config ROCKER bool default y if PCI_DEVICES - depends on PCI + depends on PCI && MSI_NONBROKEN config CAN_BUS bool diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 5e144cb4e4..9b39bccfb2 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -120,6 +120,8 @@ typedef struct E1000State_st { bool mit_irq_level; /* Tracks interrupt pin level. */ uint32_t mit_ide; /* Tracks E1000_TXD_CMD_IDE bit. */ + QEMUTimer *flush_queue_timer; + /* Compatibility flags for migration to/from qemu 1.3.0 and older */ #define E1000_FLAG_AUTONEG_BIT 0 #define E1000_FLAG_MIT_BIT 1 @@ -366,6 +368,7 @@ static void e1000_reset(void *opaque) timer_del(d->autoneg_timer); timer_del(d->mit_timer); + timer_del(d->flush_queue_timer); d->mit_timer_on = 0; d->mit_irq_level = 0; d->mit_ide = 0; @@ -392,6 +395,14 @@ set_ctrl(E1000State *s, int index, uint32_t val) } static void +e1000_flush_queue_timer(void *opaque) +{ + E1000State *s = opaque; + + qemu_flush_queued_packets(qemu_get_queue(s->nic)); +} + +static void set_rx_control(E1000State *s, int index, uint32_t val) { s->mac_reg[RCTL] = val; @@ -399,7 +410,8 @@ set_rx_control(E1000State *s, int index, uint32_t val) s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1; DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT], s->mac_reg[RCTL]); - qemu_flush_queued_packets(qemu_get_queue(s->nic)); + timer_mod(s->flush_queue_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000); } static void @@ -837,7 +849,7 @@ e1000_can_receive(NetClientState *nc) E1000State *s = qemu_get_nic_opaque(nc); return e1000x_rx_ready(&s->parent_obj, s->mac_reg) && - e1000_has_rxbufs(s, 1); + e1000_has_rxbufs(s, 1) && !timer_pending(s->flush_queue_timer); } static uint64_t rx_desc_base(E1000State *s) @@ -881,6 +893,10 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) return -1; } + if (timer_pending(s->flush_queue_timer)) { + return 0; + } + /* Pad to minimum Ethernet frame length */ if (size < sizeof(min_buf)) { iov_to_buf(iov, iovcnt, 0, min_buf, size); @@ -1637,6 +1653,8 @@ pci_e1000_uninit(PCIDevice *dev) timer_free(d->autoneg_timer); timer_del(d->mit_timer); timer_free(d->mit_timer); + timer_del(d->flush_queue_timer); + timer_free(d->flush_queue_timer); qemu_del_nic(d->nic); } @@ -1700,6 +1718,8 @@ static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp) d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d); d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d); + d->flush_queue_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, + e1000_flush_queue_timer, d); } static void qdev_e1000_reset(DeviceState *dev) diff --git a/hw/pci-bridge/Kconfig b/hw/pci-bridge/Kconfig index b167b98497..a51ec716f5 100644 --- a/hw/pci-bridge/Kconfig +++ b/hw/pci-bridge/Kconfig @@ -1,7 +1,7 @@ config PCIE_PORT bool default y if PCI_DEVICES - depends on PCI_EXPRESS + depends on PCI_EXPRESS && MSI_NONBROKEN config PXB bool @@ -10,12 +10,12 @@ config PXB config XIO3130 bool default y if PCI_DEVICES - depends on PCI_EXPRESS + depends on PCI_EXPRESS && MSI_NONBROKEN config IOH3420 bool default y if PCI_DEVICES - depends on PCI_EXPRESS + depends on PCI_EXPRESS && MSI_NONBROKEN config I82801B11 bool diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index b39ea297ba..8c16d96b3f 100644 --- a/hw/pci-host/Kconfig +++ b/hw/pci-host/Kconfig @@ -49,3 +49,4 @@ config PCI_EXPRESS_XILINX config PCI_EXPRESS_DESIGNWARE bool select PCI_EXPRESS + select MSI_NONBROKEN diff --git a/hw/pci/Kconfig b/hw/pci/Kconfig index 3b8638b51d..77f8b005ff 100644 --- a/hw/pci/Kconfig +++ b/hw/pci/Kconfig @@ -7,3 +7,9 @@ config PCI_EXPRESS config PCI_DEVICES bool + +config MSI_NONBROKEN + # selected by interrupt controllers that do not support MSI, + # or support it and have a good implementation. See commit + # 47d2b0f33c664533b8dbd5cb17faa8e6a01afe1f. + bool diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig index 2b83637511..a3465155f0 100644 --- a/hw/ppc/Kconfig +++ b/hw/ppc/Kconfig @@ -2,12 +2,14 @@ config PSERIES bool imply PCI_DEVICES imply TEST_DEVICES + imply VIRTIO_VGA select DIMM select PCI select SPAPR_VSCSI select VFIO if LINUX # needed by spapr_pci_vfio.c select XICS_SPAPR select XIVE_SPAPR + select MSI_NONBROKEN config SPAPR_RNG bool @@ -36,6 +38,7 @@ config PPC440 bool imply PCI_DEVICES imply TEST_DEVICES + imply E1000_PCI select PCI_EXPRESS select PPC4XX select SERIAL @@ -63,7 +66,6 @@ config PREP imply TEST_DEVICES select CS4231A select PREP_PCI - select I82374 select I82378 select LSI_SCSI_PCI select M48T59 @@ -97,6 +99,7 @@ config MAC_NEWWORLD config E500 bool imply AT24C + imply VIRTIO_PCI select ETSEC select OPENPIC select PLATFORM_BUS diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 49d57469fb..ad20584f26 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -1101,7 +1101,7 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq) tb_env = g_malloc0(sizeof(ppc_tb_t)); env->tb_env = tb_env; tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED; - if (env->insns_flags & PPC_SEGMENT_64B) { + if (is_book3s_arch2x(env)) { /* All Book3S 64bit CPUs implement level based DEC logic */ tb_env->flags |= PPC_DECR_UNDERFLOW_LEVEL; } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 6c16d6cfaf..b52b82d298 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1252,38 +1252,8 @@ static void *spapr_build_fdt(SpaprMachineState *spapr) _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)")); _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries")); - /* - * Add info to guest to indentify which host is it being run on - * and what is the uuid of the guest - */ - if (spapr->host_model && !g_str_equal(spapr->host_model, "none")) { - if (g_str_equal(spapr->host_model, "passthrough")) { - /* -M host-model=passthrough */ - if (kvmppc_get_host_model(&buf)) { - _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); - g_free(buf); - } - } else { - /* -M host-model=<user-string> */ - _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model)); - } - } - - if (spapr->host_serial && !g_str_equal(spapr->host_serial, "none")) { - if (g_str_equal(spapr->host_serial, "passthrough")) { - /* -M host-serial=passthrough */ - if (kvmppc_get_host_serial(&buf)) { - _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); - g_free(buf); - } - } else { - /* -M host-serial=<user-string> */ - _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial)); - } - } - + /* Guest UUID & Name*/ buf = qemu_uuid_unparse_strdup(&qemu_uuid); - _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf)); if (qemu_uuid_set) { _FDT(fdt_setprop_string(fdt, 0, "system-id", buf)); @@ -1295,6 +1265,21 @@ static void *spapr_build_fdt(SpaprMachineState *spapr) qemu_get_vm_name())); } + /* Host Model & Serial Number */ + if (spapr->host_model) { + _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model)); + } else if (smc->broken_host_serial_model && kvmppc_get_host_model(&buf)) { + _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); + g_free(buf); + } + + if (spapr->host_serial) { + _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial)); + } else if (smc->broken_host_serial_model && kvmppc_get_host_serial(&buf)) { + _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); + g_free(buf); + } + _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2)); _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); @@ -2795,13 +2780,7 @@ static void spapr_machine_init(MachineState *machine) /* advertise XIVE on POWER9 machines */ if (spapr->irq->ov5 & (SPAPR_OV5_XIVE_EXPLOIT | SPAPR_OV5_XIVE_BOTH)) { - if (ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, - 0, spapr->max_compat_pvr)) { - spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); - } else if (spapr->irq->ov5 & SPAPR_OV5_XIVE_EXPLOIT) { - error_report("XIVE-only machines require a POWER9 CPU"); - exit(1); - } + spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); } /* init CPUs */ @@ -3352,12 +3331,12 @@ static void spapr_instance_init(Object *obj) spapr_get_host_model, spapr_set_host_model, &error_abort); object_property_set_description(obj, "host-model", - "Set host's model-id to use - none|passthrough|string", &error_abort); + "Host model to advertise in guest device tree", &error_abort); object_property_add_str(obj, "host-serial", spapr_get_host_serial, spapr_set_host_serial, &error_abort); object_property_set_description(obj, "host-serial", - "Set host's system-id to use - none|passthrough|string", &error_abort); + "Host serial number to advertise in guest device tree", &error_abort); } static void spapr_machine_finalizefn(Object *obj) @@ -4381,18 +4360,14 @@ DEFINE_SPAPR_MACHINE(4_0, "4.0", true); static void spapr_machine_3_1_class_options(MachineClass *mc) { SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); - static GlobalProperty compat[] = { - { TYPE_SPAPR_MACHINE, "host-model", "passthrough" }, - { TYPE_SPAPR_MACHINE, "host-serial", "passthrough" }, - }; spapr_machine_4_0_class_options(mc); compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len); - compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); smc->update_dt_enabled = false; smc->dr_phb_enabled = false; + smc->broken_host_serial_model = true; smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN; smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index 253e4de7fd..0a84e4cf63 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -16,6 +16,7 @@ #include "hw/ppc/spapr_xive.h" #include "hw/ppc/xics.h" #include "hw/ppc/xics_spapr.h" +#include "cpu-models.h" #include "sysemu/kvm.h" #include "trace.h" @@ -582,12 +583,55 @@ SpaprIrq spapr_irq_dual = { .get_nodename = spapr_irq_get_nodename_dual, }; + +static void spapr_irq_check(SpaprMachineState *spapr, Error **errp) +{ + MachineState *machine = MACHINE(spapr); + + /* + * Sanity checks on non-P9 machines. On these, XIVE is not + * advertised, see spapr_dt_ov5_platform_support() + */ + if (!ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, + 0, spapr->max_compat_pvr)) { + /* + * If the 'dual' interrupt mode is selected, force XICS as CAS + * negotiation is useless. + */ + if (spapr->irq == &spapr_irq_dual) { + spapr->irq = &spapr_irq_xics; + return; + } + + /* + * Non-P9 machines using only XIVE is a bogus setup. We have two + * scenarios to take into account because of the compat mode: + * + * 1. POWER7/8 machines should fail to init later on when creating + * the XIVE interrupt presenters because a POWER9 exception + * model is required. + + * 2. POWER9 machines using the POWER8 compat mode won't fail and + * will let the OS boot with a partial XIVE setup : DT + * properties but no hcalls. + * + * To cover both and not confuse the OS, add an early failure in + * QEMU. + */ + if (spapr->irq == &spapr_irq_xive) { + error_setg(errp, "XIVE-only machines require a POWER9 CPU"); + return; + } + } +} + /* * sPAPR IRQ frontend routines for devices */ void spapr_irq_init(SpaprMachineState *spapr, Error **errp) { MachineState *machine = MACHINE(spapr); + Error *local_err = NULL; if (machine_kernel_irqchip_split(machine)) { error_setg(errp, "kernel_irqchip split mode not supported on pseries"); @@ -600,6 +644,12 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp) return; } + spapr_irq_check(spapr, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + /* Initialize the MSI IRQ allocator. */ if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { spapr_irq_msi_init(spapr, spapr->irq->nr_msis); diff --git a/hw/rdma/Kconfig b/hw/rdma/Kconfig new file mode 100644 index 0000000000..8e2211288f --- /dev/null +++ b/hw/rdma/Kconfig @@ -0,0 +1,3 @@ +config VMW_PVRDMA + default y if PCI_DEVICES + depends on PVRDMA && PCI && MSI_NONBROKEN diff --git a/hw/rdma/Makefile.objs b/hw/rdma/Makefile.objs index c354e60e5b..819bb12a35 100644 --- a/hw/rdma/Makefile.objs +++ b/hw/rdma/Makefile.objs @@ -1,5 +1,3 @@ -ifeq ($(CONFIG_PVRDMA),y) -obj-$(CONFIG_PCI) += rdma_utils.o rdma_backend.o rdma_rm.o rdma.o -obj-$(CONFIG_PCI) += vmw/pvrdma_dev_ring.o vmw/pvrdma_cmd.o \ +obj-$(CONFIG_VMW_PVRDMA) += rdma_utils.o rdma_backend.o rdma_rm.o rdma.o +obj-$(CONFIG_VMW_PVRDMA) += vmw/pvrdma_dev_ring.o vmw/pvrdma_cmd.o \ vmw/pvrdma_qp_ops.o vmw/pvrdma_main.o -endif diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 8c7fc1f31d..8674211085 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -6,6 +6,7 @@ config HART config SIFIVE bool + select MSI_NONBROKEN config SIFIVE_E bool diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c index 1c703e1a37..ac768e6c27 100644 --- a/hw/riscv/sifive_plic.c +++ b/hw/riscv/sifive_plic.c @@ -22,6 +22,7 @@ #include "qemu/log.h" #include "qemu/error-report.h" #include "hw/sysbus.h" +#include "hw/pci/msi.h" #include "target/riscv/cpu.h" #include "sysemu/sysemu.h" #include "hw/riscv/sifive_plic.h" @@ -458,6 +459,8 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp) exit(1); } } + + msi_nonbroken = true; } static void sifive_plic_class_init(ObjectClass *klass, void *data) diff --git a/hw/s390x/Kconfig b/hw/s390x/Kconfig index a7046ea41f..5e7d8a2bae 100644 --- a/hw/s390x/Kconfig +++ b/hw/s390x/Kconfig @@ -9,3 +9,4 @@ config S390_CCW_VIRTIO select S390_FLIC select SCLPCONSOLE select VIRTIO_CCW + select MSI_NONBROKEN diff --git a/hw/sh4/Kconfig b/hw/sh4/Kconfig index 8597613a35..593662d28a 100644 --- a/hw/sh4/Kconfig +++ b/hw/sh4/Kconfig @@ -2,6 +2,7 @@ config R2D bool imply PCI_DEVICES imply TEST_DEVICES + imply RTL8139_PCI select I82378 if TEST_DEVICES select IDE_MMIO select PFLASH_CFI02 diff --git a/hw/sparc64/Kconfig b/hw/sparc64/Kconfig index 4a8166ebb7..d4d76a89be 100644 --- a/hw/sparc64/Kconfig +++ b/hw/sparc64/Kconfig @@ -3,13 +3,13 @@ config SUN4U imply PCI_DEVICES imply SUNHME imply TEST_DEVICES + imply PARALLEL select M48T59 select ISA_BUS select FDC select SERIAL_ISA select PCI_SABRE select IDE_CMD646 - select PARALLEL select PCKBD select SIMBA diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 196a9f7200..81cf5ab7a5 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -1200,7 +1200,7 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) if (head == 0) return 0; - for (cur = head; cur; cur = next_ed) { + for (cur = head; cur && link_cnt++ < ED_LINK_LIMIT; cur = next_ed) { if (ohci_read_ed(ohci, cur, &ed)) { trace_usb_ohci_ed_read_error(cur); ohci_die(ohci); @@ -1209,11 +1209,6 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) next_ed = ed.next & OHCI_DPTR_MASK; - if (++link_cnt > ED_LINK_LIMIT) { - ohci_die(ohci); - return 0; - } - if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) { uint32_t addr; /* Cancel pending packets for ED that have been paused. */ diff --git a/include/block/block.h b/include/block/block.h index e452988b66..c7a26199aa 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -83,8 +83,13 @@ typedef enum { */ BDRV_REQ_SERIALISING = 0x80, + /* Execute the request only if the operation can be offloaded or otherwise + * be executed efficiently, but return an error instead of using a slow + * fallback. */ + BDRV_REQ_NO_FALLBACK = 0x100, + /* Mask of valid flags */ - BDRV_REQ_MASK = 0xff, + BDRV_REQ_MASK = 0x1ff, } BdrvRequestFlags; typedef struct BlockSizes { diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h index 6799614e56..ba223dd1f1 100644 --- a/include/block/raw-aio.h +++ b/include/block/raw-aio.h @@ -40,6 +40,7 @@ /* AIO flags */ #define QEMU_AIO_MISALIGNED 0x1000 #define QEMU_AIO_BLKDEV 0x2000 +#define QEMU_AIO_NO_FALLBACK 0x4000 /* linux-aio.c - Linux native implementation */ diff --git a/include/hw/block/block.h b/include/hw/block/block.h index e9f9e2223f..d06f25aa0f 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -11,7 +11,7 @@ #ifndef HW_BLOCK_H #define HW_BLOCK_H -#include "qemu-common.h" +#include "exec/hwaddr.h" #include "qapi/qapi-types-block-core.h" /* Configuration */ @@ -70,6 +70,11 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) DEFINE_PROP_BLOCKDEV_ON_ERROR("werror", _state, _conf.werror, \ BLOCKDEV_ON_ERROR_AUTO) +/* Backend access helpers */ + +bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size, + Error **errp); + /* Configuration helpers */ bool blkconf_geometry(BlockConf *conf, int *trans, diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index c11e3d5b34..536f62667b 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -105,8 +105,8 @@ struct VTDAddressSpace { uint8_t devfn; AddressSpace as; IOMMUMemoryRegion iommu; - MemoryRegion root; - MemoryRegion sys_alias; + MemoryRegion root; /* The root container of the device */ + MemoryRegion nodmar; /* The alias of shared nodmar MR */ MemoryRegion iommu_ir; /* Interrupt region: 0xfeeXXXXX */ IntelIOMMUState *iommu_state; VTDContextCacheEntry context_cache_entry; @@ -221,6 +221,9 @@ union VTD_IR_MSIAddress { struct IntelIOMMUState { X86IOMMUState x86_iommu; MemoryRegion csrmem; + MemoryRegion mr_nodmar; + MemoryRegion mr_ir; + MemoryRegion mr_sys_alias; uint8_t csr[DMAR_REG_SIZE]; /* register values */ uint8_t wmask[DMAR_REG_SIZE]; /* R/W bytes */ uint8_t w1cmask[DMAR_REG_SIZE]; /* RW1C(Write 1 to Clear) bytes */ diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 2b4c05a2ec..5ea8081041 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -118,6 +118,7 @@ struct SpaprMachineClass { bool use_ohci_by_default; /* use USB-OHCI instead of XHCI */ bool pre_2_10_has_unused_icps; bool legacy_irq_allocation; + bool broken_host_serial_model; /* present real host info to the guest */ void (*phb_placement)(SpaprMachineState *spapr, uint32_t index, uint64_t *buid, hwaddr *pio, @@ -1649,10 +1649,17 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr, uint64_t size, void *ptr) { - memory_region_init_ram_ptr(mr, owner, name, size, ptr); + memory_region_init(mr, owner, name, size); + mr->ram = true; + mr->terminates = true; mr->ram_device = true; mr->ops = &ram_device_mem_ops; mr->opaque = mr; + mr->destructor = memory_region_destructor_ram; + mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */ + assert(ptr != NULL); + mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal); } void memory_region_init_alias(MemoryRegion *mr, diff --git a/migration/colo.c b/migration/colo.c index 5ba610dc01..238a6d62c7 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -38,6 +38,9 @@ static bool vmstate_loading; static Notifier packets_compare_notifier; +/* User need to know colo mode after COLO failover */ +static COLOMode last_colo_mode; + #define COLO_BUFFER_BASE_SIZE (4 * 1024 * 1024) bool migration_in_colo_state(void) @@ -121,6 +124,7 @@ static void secondary_vm_do_failover(void) } /* Notify COLO incoming thread that failover work is finished */ qemu_sem_post(&mis->colo_incoming_sem); + /* For Secondary VM, jump to incoming co */ if (mis->migration_incoming_co) { qemu_coroutine_enter(mis->migration_incoming_co); @@ -196,10 +200,16 @@ void colo_do_failover(MigrationState *s) vm_stop_force_state(RUN_STATE_COLO); } - if (get_colo_mode() == COLO_MODE_PRIMARY) { + switch (get_colo_mode()) { + case COLO_MODE_PRIMARY: primary_vm_do_failover(); - } else { + break; + case COLO_MODE_SECONDARY: secondary_vm_do_failover(); + break; + default: + error_report("colo_do_failover failed because the colo mode" + " could not be obtained"); } } @@ -257,16 +267,21 @@ COLOStatus *qmp_query_colo_status(Error **errp) COLOStatus *s = g_new0(COLOStatus, 1); s->mode = get_colo_mode(); + s->last_mode = last_colo_mode; switch (failover_get_state()) { case FAILOVER_STATUS_NONE: s->reason = COLO_EXIT_REASON_NONE; break; - case FAILOVER_STATUS_REQUIRE: + case FAILOVER_STATUS_COMPLETED: s->reason = COLO_EXIT_REASON_REQUEST; break; default: - s->reason = COLO_EXIT_REASON_ERROR; + if (migration_in_colo_state()) { + s->reason = COLO_EXIT_REASON_PROCESSING; + } else { + s->reason = COLO_EXIT_REASON_ERROR; + } } return s; @@ -504,6 +519,12 @@ static void colo_process_checkpoint(MigrationState *s) Error *local_err = NULL; int ret; + last_colo_mode = get_colo_mode(); + if (last_colo_mode != COLO_MODE_PRIMARY) { + error_report("COLO mode must be COLO_MODE_PRIMARY"); + return; + } + failover_init_state(); s->rp_state.from_dst_file = qemu_file_get_return_path(s->to_dst_file); @@ -578,16 +599,13 @@ out: * or the user triggered failover. */ switch (failover_get_state()) { - case FAILOVER_STATUS_NONE: - qapi_event_send_colo_exit(COLO_MODE_PRIMARY, - COLO_EXIT_REASON_ERROR); - break; - case FAILOVER_STATUS_REQUIRE: + case FAILOVER_STATUS_COMPLETED: qapi_event_send_colo_exit(COLO_MODE_PRIMARY, COLO_EXIT_REASON_REQUEST); break; default: - abort(); + qapi_event_send_colo_exit(COLO_MODE_PRIMARY, + COLO_EXIT_REASON_ERROR); } /* Hope this not to be too long to wait here */ @@ -680,6 +698,12 @@ void *colo_process_incoming_thread(void *opaque) migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_COLO); + last_colo_mode = get_colo_mode(); + if (last_colo_mode != COLO_MODE_SECONDARY) { + error_report("COLO mode must be COLO_MODE_SECONDARY"); + return NULL; + } + failover_init_state(); mis->to_src_file = qemu_file_get_return_path(mis->from_src_file); @@ -849,17 +873,18 @@ out: error_report_err(local_err); } + /* + * There are only two reasons we can get here, some error happened + * or the user triggered failover. + */ switch (failover_get_state()) { - case FAILOVER_STATUS_NONE: - qapi_event_send_colo_exit(COLO_MODE_SECONDARY, - COLO_EXIT_REASON_ERROR); - break; - case FAILOVER_STATUS_REQUIRE: + case FAILOVER_STATUS_COMPLETED: qapi_event_send_colo_exit(COLO_MODE_SECONDARY, COLO_EXIT_REASON_REQUEST); break; default: - abort(); + qapi_event_send_colo_exit(COLO_MODE_SECONDARY, + COLO_EXIT_REASON_ERROR); } if (fb) { diff --git a/migration/migration.c b/migration/migration.c index df6fd8e0e5..69f75124c9 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -82,7 +82,6 @@ /* The delay time (in ms) between two COLO checkpoints */ #define DEFAULT_MIGRATE_X_CHECKPOINT_DELAY (200 * 100) #define DEFAULT_MIGRATE_MULTIFD_CHANNELS 2 -#define DEFAULT_MIGRATE_MULTIFD_PAGE_COUNT 16 /* Background transfer rate for postcopy, 0 means unlimited, note * that page requests can still exceed this limit. @@ -758,6 +757,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) params->tls_creds = g_strdup(s->parameters.tls_creds); params->has_tls_hostname = true; params->tls_hostname = g_strdup(s->parameters.tls_hostname); + params->has_tls_authz = true; + params->tls_authz = g_strdup(s->parameters.tls_authz); params->has_max_bandwidth = true; params->max_bandwidth = s->parameters.max_bandwidth; params->has_downtime_limit = true; @@ -766,10 +767,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) params->x_checkpoint_delay = s->parameters.x_checkpoint_delay; params->has_block_incremental = true; params->block_incremental = s->parameters.block_incremental; - params->has_x_multifd_channels = true; - params->x_multifd_channels = s->parameters.x_multifd_channels; - params->has_x_multifd_page_count = true; - params->x_multifd_page_count = s->parameters.x_multifd_page_count; + params->has_multifd_channels = true; + params->multifd_channels = s->parameters.multifd_channels; params->has_xbzrle_cache_size = true; params->xbzrle_cache_size = s->parameters.xbzrle_cache_size; params->has_max_postcopy_bandwidth = true; @@ -1152,20 +1151,12 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp) /* x_checkpoint_delay is now always positive */ - if (params->has_x_multifd_channels && (params->x_multifd_channels < 1)) { + if (params->has_multifd_channels && (params->multifd_channels < 1)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_channels", "is invalid, it should be in the range of 1 to 255"); return false; } - if (params->has_x_multifd_page_count && - (params->x_multifd_page_count < 1 || - params->x_multifd_page_count > 10000)) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, - "multifd_page_count", - "is invalid, it should be in the range of 1 to 10000"); - return false; - } if (params->has_xbzrle_cache_size && (params->xbzrle_cache_size < qemu_target_page_size() || @@ -1274,11 +1265,8 @@ static void migrate_params_test_apply(MigrateSetParameters *params, if (params->has_block_incremental) { dest->block_incremental = params->block_incremental; } - if (params->has_x_multifd_channels) { - dest->x_multifd_channels = params->x_multifd_channels; - } - if (params->has_x_multifd_page_count) { - dest->x_multifd_page_count = params->x_multifd_page_count; + if (params->has_multifd_channels) { + dest->multifd_channels = params->multifd_channels; } if (params->has_xbzrle_cache_size) { dest->xbzrle_cache_size = params->xbzrle_cache_size; @@ -1345,9 +1333,15 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) s->parameters.tls_hostname = g_strdup(params->tls_hostname->u.s); } + if (params->has_tls_authz) { + g_free(s->parameters.tls_authz); + assert(params->tls_authz->type == QTYPE_QSTRING); + s->parameters.tls_authz = g_strdup(params->tls_authz->u.s); + } + if (params->has_max_bandwidth) { s->parameters.max_bandwidth = params->max_bandwidth; - if (s->to_dst_file) { + if (s->to_dst_file && !migration_in_postcopy()) { qemu_file_set_rate_limit(s->to_dst_file, s->parameters.max_bandwidth / XFER_LIMIT_RATIO); } @@ -1367,11 +1361,8 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) if (params->has_block_incremental) { s->parameters.block_incremental = params->block_incremental; } - if (params->has_x_multifd_channels) { - s->parameters.x_multifd_channels = params->x_multifd_channels; - } - if (params->has_x_multifd_page_count) { - s->parameters.x_multifd_page_count = params->x_multifd_page_count; + if (params->has_multifd_channels) { + s->parameters.multifd_channels = params->multifd_channels; } if (params->has_xbzrle_cache_size) { s->parameters.xbzrle_cache_size = params->xbzrle_cache_size; @@ -1379,6 +1370,10 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) } if (params->has_max_postcopy_bandwidth) { s->parameters.max_postcopy_bandwidth = params->max_postcopy_bandwidth; + if (s->to_dst_file && migration_in_postcopy()) { + qemu_file_set_rate_limit(s->to_dst_file, + s->parameters.max_postcopy_bandwidth / XFER_LIMIT_RATIO); + } } if (params->has_max_cpu_throttle) { s->parameters.max_cpu_throttle = params->max_cpu_throttle; @@ -2130,7 +2125,7 @@ bool migrate_use_multifd(void) s = migrate_get_current(); - return s->enabled_capabilities[MIGRATION_CAPABILITY_X_MULTIFD]; + return s->enabled_capabilities[MIGRATION_CAPABILITY_MULTIFD]; } bool migrate_pause_before_switchover(void) @@ -2149,16 +2144,7 @@ int migrate_multifd_channels(void) s = migrate_get_current(); - return s->parameters.x_multifd_channels; -} - -int migrate_multifd_page_count(void) -{ - MigrationState *s; - - s = migrate_get_current(); - - return s->parameters.x_multifd_page_count; + return s->parameters.multifd_channels; } int migrate_use_xbzrle(void) @@ -3400,12 +3386,9 @@ static Property migration_properties[] = { DEFINE_PROP_UINT32("x-checkpoint-delay", MigrationState, parameters.x_checkpoint_delay, DEFAULT_MIGRATE_X_CHECKPOINT_DELAY), - DEFINE_PROP_UINT8("x-multifd-channels", MigrationState, - parameters.x_multifd_channels, + DEFINE_PROP_UINT8("multifd-channels", MigrationState, + parameters.multifd_channels, DEFAULT_MIGRATE_MULTIFD_CHANNELS), - DEFINE_PROP_UINT32("x-multifd-page-count", MigrationState, - parameters.x_multifd_page_count, - DEFAULT_MIGRATE_MULTIFD_PAGE_COUNT), DEFINE_PROP_SIZE("xbzrle-cache-size", MigrationState, parameters.xbzrle_cache_size, DEFAULT_MIGRATE_XBZRLE_CACHE_SIZE), @@ -3440,7 +3423,7 @@ static Property migration_properties[] = { DEFINE_PROP_MIG_CAP("x-release-ram", MIGRATION_CAPABILITY_RELEASE_RAM), DEFINE_PROP_MIG_CAP("x-block", MIGRATION_CAPABILITY_BLOCK), DEFINE_PROP_MIG_CAP("x-return-path", MIGRATION_CAPABILITY_RETURN_PATH), - DEFINE_PROP_MIG_CAP("x-multifd", MIGRATION_CAPABILITY_X_MULTIFD), + DEFINE_PROP_MIG_CAP("x-multifd", MIGRATION_CAPABILITY_MULTIFD), DEFINE_PROP_END_OF_LIST(), }; @@ -3494,8 +3477,7 @@ static void migration_instance_init(Object *obj) params->has_downtime_limit = true; params->has_x_checkpoint_delay = true; params->has_block_incremental = true; - params->has_x_multifd_channels = true; - params->has_x_multifd_page_count = true; + params->has_multifd_channels = true; params->has_xbzrle_cache_size = true; params->has_max_postcopy_bandwidth = true; params->has_max_cpu_throttle = true; diff --git a/migration/migration.h b/migration/migration.h index 99e99e56bd..0f986935e1 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -274,7 +274,6 @@ bool migrate_auto_converge(void); bool migrate_use_multifd(void); bool migrate_pause_before_switchover(void); int migrate_multifd_channels(void); -int migrate_multifd_page_count(void); int migrate_use_xbzrle(void); int64_t migrate_xbzrle_cache_size(void); diff --git a/migration/ram.c b/migration/ram.c index 35bd6213e9..d7f8fe45a8 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -583,20 +583,29 @@ exit: #define MULTIFD_FLAG_SYNC (1 << 0) +/* This value needs to be a multiple of qemu_target_page_size() */ +#define MULTIFD_PACKET_SIZE (512 * 1024) + typedef struct { uint32_t magic; uint32_t version; unsigned char uuid[16]; /* QemuUUID */ uint8_t id; + uint8_t unused1[7]; /* Reserved for future use */ + uint64_t unused2[4]; /* Reserved for future use */ } __attribute__((packed)) MultiFDInit_t; typedef struct { uint32_t magic; uint32_t version; uint32_t flags; - uint32_t size; - uint32_t used; + /* maximum number of allocated pages */ + uint32_t pages_alloc; + uint32_t pages_used; + /* size of the next packet that contains pages */ + uint32_t next_packet_size; uint64_t packet_num; + uint64_t unused[4]; /* Reserved for future use */ char ramblock[256]; uint64_t offset[]; } __attribute__((packed)) MultiFDPacket_t; @@ -643,6 +652,8 @@ typedef struct { MultiFDPacket_t *packet; /* multifd flags for each packet */ uint32_t flags; + /* size of the next packet that contains pages */ + uint32_t next_packet_size; /* global number of generated multifd packets */ uint64_t packet_num; /* thread local variables */ @@ -679,6 +690,8 @@ typedef struct { /* global number of generated multifd packets */ uint64_t packet_num; /* thread local variables */ + /* size of the next packet that contains pages */ + uint32_t next_packet_size; /* packets sent through this channel */ uint64_t num_packets; /* pages sent through this channel */ @@ -776,13 +789,15 @@ static void multifd_pages_clear(MultiFDPages_t *pages) static void multifd_send_fill_packet(MultiFDSendParams *p) { MultiFDPacket_t *packet = p->packet; + uint32_t page_max = MULTIFD_PACKET_SIZE / qemu_target_page_size(); int i; packet->magic = cpu_to_be32(MULTIFD_MAGIC); packet->version = cpu_to_be32(MULTIFD_VERSION); packet->flags = cpu_to_be32(p->flags); - packet->size = cpu_to_be32(migrate_multifd_page_count()); - packet->used = cpu_to_be32(p->pages->used); + packet->pages_alloc = cpu_to_be32(page_max); + packet->pages_used = cpu_to_be32(p->pages->used); + packet->next_packet_size = cpu_to_be32(p->next_packet_size); packet->packet_num = cpu_to_be64(p->packet_num); if (p->pages->block) { @@ -797,6 +812,7 @@ static void multifd_send_fill_packet(MultiFDSendParams *p) static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp) { MultiFDPacket_t *packet = p->packet; + uint32_t pages_max = MULTIFD_PACKET_SIZE / qemu_target_page_size(); RAMBlock *block; int i; @@ -818,22 +834,35 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp) p->flags = be32_to_cpu(packet->flags); - packet->size = be32_to_cpu(packet->size); - if (packet->size > migrate_multifd_page_count()) { + packet->pages_alloc = be32_to_cpu(packet->pages_alloc); + /* + * If we recevied a packet that is 100 times bigger than expected + * just stop migration. It is a magic number. + */ + if (packet->pages_alloc > pages_max * 100) { error_setg(errp, "multifd: received packet " - "with size %d and expected maximum size %d", - packet->size, migrate_multifd_page_count()) ; + "with size %d and expected a maximum size of %d", + packet->pages_alloc, pages_max * 100) ; return -1; } + /* + * We received a packet that is bigger than expected but inside + * reasonable limits (see previous comment). Just reallocate. + */ + if (packet->pages_alloc > p->pages->allocated) { + multifd_pages_clear(p->pages); + multifd_pages_init(packet->pages_alloc); + } - p->pages->used = be32_to_cpu(packet->used); - if (p->pages->used > packet->size) { + p->pages->used = be32_to_cpu(packet->pages_used); + if (p->pages->used > packet->pages_alloc) { error_setg(errp, "multifd: received packet " - "with size %d and expected maximum size %d", - p->pages->used, packet->size) ; + "with %d pages and expected maximum pages are %d", + p->pages->used, packet->pages_alloc) ; return -1; } + p->next_packet_size = be32_to_cpu(packet->next_packet_size); p->packet_num = be64_to_cpu(packet->packet_num); if (p->pages->used) { @@ -1073,6 +1102,7 @@ static void *multifd_send_thread(void *opaque) uint64_t packet_num = p->packet_num; uint32_t flags = p->flags; + p->next_packet_size = used * qemu_target_page_size(); multifd_send_fill_packet(p); p->flags = 0; p->num_packets++; @@ -1080,7 +1110,8 @@ static void *multifd_send_thread(void *opaque) p->pages->used = 0; qemu_mutex_unlock(&p->mutex); - trace_multifd_send(p->id, packet_num, used, flags); + trace_multifd_send(p->id, packet_num, used, flags, + p->next_packet_size); ret = qio_channel_write_all(p->c, (void *)p->packet, p->packet_len, &local_err); @@ -1088,9 +1119,12 @@ static void *multifd_send_thread(void *opaque) break; } - ret = qio_channel_writev_all(p->c, p->pages->iov, used, &local_err); - if (ret != 0) { - break; + if (used) { + ret = qio_channel_writev_all(p->c, p->pages->iov, + used, &local_err); + if (ret != 0) { + break; + } } qemu_mutex_lock(&p->mutex); @@ -1148,7 +1182,7 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) int multifd_save_setup(void) { int thread_count; - uint32_t page_count = migrate_multifd_page_count(); + uint32_t page_count = MULTIFD_PACKET_SIZE / qemu_target_page_size(); uint8_t i; if (!migrate_use_multifd()) { @@ -1312,14 +1346,18 @@ static void *multifd_recv_thread(void *opaque) used = p->pages->used; flags = p->flags; - trace_multifd_recv(p->id, p->packet_num, used, flags); + trace_multifd_recv(p->id, p->packet_num, used, flags, + p->next_packet_size); p->num_packets++; p->num_pages += used; qemu_mutex_unlock(&p->mutex); - ret = qio_channel_readv_all(p->c, p->pages->iov, used, &local_err); - if (ret != 0) { - break; + if (used) { + ret = qio_channel_readv_all(p->c, p->pages->iov, + used, &local_err); + if (ret != 0) { + break; + } } if (flags & MULTIFD_FLAG_SYNC) { @@ -1344,7 +1382,7 @@ static void *multifd_recv_thread(void *opaque) int multifd_load_setup(void) { int thread_count; - uint32_t page_count = migrate_multifd_page_count(); + uint32_t page_count = MULTIFD_PACKET_SIZE / qemu_target_page_size(); uint8_t i; if (!migrate_use_multifd()) { diff --git a/migration/rdma.c b/migration/rdma.c index 63c118af09..c1bcece53b 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -641,10 +641,14 @@ static int qemu_rdma_init_one_block(RAMBlock *rb, void *opaque) static int qemu_rdma_init_ram_blocks(RDMAContext *rdma) { RDMALocalBlocks *local = &rdma->local_ram_blocks; + int ret; assert(rdma->blockmap == NULL); memset(local, 0, sizeof *local); - foreach_not_ignored_block(qemu_rdma_init_one_block, rdma); + ret = foreach_not_ignored_block(qemu_rdma_init_one_block, rdma); + if (ret) { + return ret; + } trace_qemu_rdma_init_ram_blocks(local->nb_blocks); rdma->dest_blocks = g_new0(RDMADestBlock, rdma->local_ram_blocks.nb_blocks); diff --git a/migration/tls.c b/migration/tls.c index 3b9e8c9263..5171afc6c4 100644 --- a/migration/tls.c +++ b/migration/tls.c @@ -94,7 +94,7 @@ void migration_tls_channel_process_incoming(MigrationState *s, tioc = qio_channel_tls_new_server( ioc, creds, - NULL, /* XXX pass ACL name */ + s->parameters.tls_authz, errp); if (!tioc) { return; diff --git a/migration/trace-events b/migration/trace-events index 5da4512030..de2e136e57 100644 --- a/migration/trace-events +++ b/migration/trace-events @@ -80,13 +80,13 @@ get_queued_page_not_dirty(const char *block_name, uint64_t tmp_offset, unsigned migration_bitmap_sync_start(void) "" migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64 migration_throttle(void) "" -multifd_recv(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags) "channel %d packet number %" PRIu64 " pages %d flags 0x%x" +multifd_recv(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags, uint32_t next_packet_size) "channel %d packet number %" PRIu64 " pages %d flags 0x%x next packet size %d" multifd_recv_sync_main(long packet_num) "packet num %ld" multifd_recv_sync_main_signal(uint8_t id) "channel %d" multifd_recv_sync_main_wait(uint8_t id) "channel %d" multifd_recv_thread_end(uint8_t id, uint64_t packets, uint64_t pages) "channel %d packets %" PRIu64 " pages %" PRIu64 multifd_recv_thread_start(uint8_t id) "%d" -multifd_send(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags) "channel %d packet_num %" PRIu64 " pages %d flags 0x%x" +multifd_send(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags, uint32_t next_packet_size) "channel %d packet_num %" PRIu64 " pages %d flags 0x%x next packet size %d" multifd_send_sync_main(long packet_num) "packet num %ld" multifd_send_sync_main_signal(uint8_t id) "channel %d" multifd_send_sync_main_wait(uint8_t id) "channel %d" diff --git a/net/socket.c b/net/socket.c index 90ef3517be..c92354049b 100644 --- a/net/socket.c +++ b/net/socket.c @@ -119,9 +119,13 @@ static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, ssize_t ret; do { - ret = qemu_sendto(s->fd, buf, size, 0, - (struct sockaddr *)&s->dgram_dst, - sizeof(s->dgram_dst)); + if (s->dgram_dst.sin_family != AF_UNIX) { + ret = qemu_sendto(s->fd, buf, size, 0, + (struct sockaddr *)&s->dgram_dst, + sizeof(s->dgram_dst)); + } else { + ret = send(s->fd, buf, size, 0); + } } while (ret == -1 && errno == EINTR); if (ret == -1 && errno == EAGAIN) { @@ -336,6 +340,15 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, int newfd; NetClientState *nc; NetSocketState *s; + SocketAddress *sa; + SocketAddressType sa_type; + + sa = socket_local_address(fd, errp); + if (!sa) { + return NULL; + } + sa_type = sa->type; + qapi_free_SocketAddress(sa); /* fd passed: multicast: "learn" dgram_dst address from bound address and save it * Because this may be "shared" socket from a "master" process, datagrams would be recv() @@ -379,8 +392,12 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, "socket: fd=%d (cloned mcast=%s:%d)", fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); } else { + if (sa_type == SOCKET_ADDRESS_TYPE_UNIX) { + s->dgram_dst.sin_family = AF_UNIX; + } + snprintf(nc->info_str, sizeof(nc->info_str), - "socket: fd=%d", fd); + "socket: fd=%d %s", fd, SocketAddressType_str(sa_type)); } return s; @@ -592,7 +592,7 @@ int net_init_bridge(const Netdev *netdev, const char *name, return -1; } - fcntl(fd, F_SETFL, O_NONBLOCK); + qemu_set_nonblock(fd); vnet_hdr = tap_probe_vnet_hdr(fd); s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr); @@ -707,7 +707,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, } return; } - fcntl(vhostfd, F_SETFL, O_NONBLOCK); + qemu_set_nonblock(vhostfd); } options.opaque = (void *)(uintptr_t)vhostfd; @@ -791,7 +791,7 @@ int net_init_tap(const Netdev *netdev, const char *name, return -1; } - fcntl(fd, F_SETFL, O_NONBLOCK); + qemu_set_nonblock(fd); vnet_hdr = tap_probe_vnet_hdr(fd); @@ -839,7 +839,7 @@ int net_init_tap(const Netdev *netdev, const char *name, goto free_fail; } - fcntl(fd, F_SETFL, O_NONBLOCK); + qemu_set_nonblock(fd); if (i == 0) { vnet_hdr = tap_probe_vnet_hdr(fd); @@ -887,7 +887,7 @@ free_fail: return -1; } - fcntl(fd, F_SETFL, O_NONBLOCK); + qemu_set_nonblock(fd); vnet_hdr = tap_probe_vnet_hdr(fd); net_init_tap_one(tap, peer, "bridge", name, ifname, diff --git a/qapi/migration.json b/qapi/migration.json index 5684733754..cfde29acf8 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -401,7 +401,7 @@ # @pause-before-switchover: Pause outgoing migration before serialising device # state and before disabling block IO (since 2.11) # -# @x-multifd: Use more than one fd for migration (since 2.11) +# @multifd: Use more than one fd for migration (since 4.0) # # @dirty-bitmaps: If enabled, QEMU will migrate named dirty bitmaps. # (since 2.12) @@ -420,7 +420,7 @@ { 'enum': 'MigrationCapability', 'data': ['xbzrle', 'rdma-pin-all', 'auto-converge', 'zero-blocks', 'compress', 'events', 'postcopy-ram', 'x-colo', 'release-ram', - 'block', 'return-path', 'pause-before-switchover', 'x-multifd', + 'block', 'return-path', 'pause-before-switchover', 'multifd', 'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate', 'x-ignore-shared' ] } @@ -541,6 +541,12 @@ # hostname must be provided so that the server's x509 # certificate identity can be validated. (Since 2.7) # +# @tls-authz: ID of the 'authz' object subclass that provides access control +# checking of the TLS x509 certificate distinguished name. +# This object is only resolved at time of use, so can be deleted +# and recreated on the fly while the migration server is active. +# If missing, it will default to denying access (Since 4.0) +# # @max-bandwidth: to set maximum speed for migration. maximum speed in # bytes per second. (Since 2.8) # @@ -557,13 +563,10 @@ # migrated and the destination must already have access to the # same backing chain as was used on the source. (since 2.10) # -# @x-multifd-channels: Number of channels used to migrate data in -# parallel. This is the same number that the -# number of sockets used for migration. The -# default value is 2 (since 2.11) -# -# @x-multifd-page-count: Number of pages sent together to a thread. -# The default value is 16 (since 2.11) +# @multifd-channels: Number of channels used to migrate data in +# parallel. This is the same number that the +# number of sockets used for migration. The +# default value is 2 (since 4.0) # # @xbzrle-cache-size: cache size to be used by XBZRLE migration. It # needs to be a multiple of the target page size @@ -585,9 +588,9 @@ 'compress-level', 'compress-threads', 'decompress-threads', 'compress-wait-thread', 'cpu-throttle-initial', 'cpu-throttle-increment', - 'tls-creds', 'tls-hostname', 'max-bandwidth', + 'tls-creds', 'tls-hostname', 'tls-authz', 'max-bandwidth', 'downtime-limit', 'x-checkpoint-delay', 'block-incremental', - 'x-multifd-channels', 'x-multifd-page-count', + 'multifd-channels', 'xbzrle-cache-size', 'max-postcopy-bandwidth', 'max-cpu-throttle' ] } @@ -662,13 +665,10 @@ # migrated and the destination must already have access to the # same backing chain as was used on the source. (since 2.10) # -# @x-multifd-channels: Number of channels used to migrate data in -# parallel. This is the same number that the -# number of sockets used for migration. The -# default value is 2 (since 2.11) -# -# @x-multifd-page-count: Number of pages sent together to a thread. -# The default value is 16 (since 2.11) +# @multifd-channels: Number of channels used to migrate data in +# parallel. This is the same number that the +# number of sockets used for migration. The +# default value is 2 (since 4.0) # # @xbzrle-cache-size: cache size to be used by XBZRLE migration. It # needs to be a multiple of the target page size @@ -699,12 +699,12 @@ '*cpu-throttle-increment': 'int', '*tls-creds': 'StrOrNull', '*tls-hostname': 'StrOrNull', + '*tls-authz': 'StrOrNull', '*max-bandwidth': 'int', '*downtime-limit': 'int', '*x-checkpoint-delay': 'int', '*block-incremental': 'bool', - '*x-multifd-channels': 'int', - '*x-multifd-page-count': 'int', + '*multifd-channels': 'int', '*xbzrle-cache-size': 'size', '*max-postcopy-bandwidth': 'size', '*max-cpu-throttle': 'int' } } @@ -780,6 +780,10 @@ # associated with the migration URI, if any. (Since 2.9) # Note: 2.8 reports this by omitting tls-hostname instead. # +# @tls-authz: ID of the 'authz' object subclass that provides access control +# checking of the TLS x509 certificate distinguished name. (Since +# 4.0) +# # @max-bandwidth: to set maximum speed for migration. maximum speed in # bytes per second. (Since 2.8) # @@ -795,13 +799,10 @@ # migrated and the destination must already have access to the # same backing chain as was used on the source. (since 2.10) # -# @x-multifd-channels: Number of channels used to migrate data in -# parallel. This is the same number that the -# number of sockets used for migration. -# The default value is 2 (since 2.11) -# -# @x-multifd-page-count: Number of pages sent together to a thread. -# The default value is 16 (since 2.11) +# @multifd-channels: Number of channels used to migrate data in +# parallel. This is the same number that the +# number of sockets used for migration. +# The default value is 2 (since 4.0) # # @xbzrle-cache-size: cache size to be used by XBZRLE migration. It # needs to be a multiple of the target page size @@ -831,12 +832,12 @@ '*cpu-throttle-increment': 'uint8', '*tls-creds': 'str', '*tls-hostname': 'str', + '*tls-authz': 'str', '*max-bandwidth': 'size', '*downtime-limit': 'uint64', '*x-checkpoint-delay': 'uint32', '*block-incremental': 'bool' , - '*x-multifd-channels': 'uint8', - '*x-multifd-page-count': 'uint32', + '*multifd-channels': 'uint8', '*xbzrle-cache-size': 'size', '*max-postcopy-bandwidth': 'size', '*max-cpu-throttle':'uint8'} } @@ -1037,19 +1038,22 @@ ## # @COLOExitReason: # -# The reason for a COLO exit +# The reason for a COLO exit. +# +# @none: failover has never happened. This state does not occur +# in the COLO_EXIT event, and is only visible in the result of +# query-colo-status. # -# @none: no failover has ever happened. This can't occur in the -# COLO_EXIT event, only in the result of query-colo-status. +# @request: COLO exit is due to an external request. # -# @request: COLO exit is due to an external request +# @error: COLO exit is due to an internal error. # -# @error: COLO exit is due to an internal error +# @processing: COLO is currently handling a failover (since 4.0). # # Since: 3.1 ## { 'enum': 'COLOExitReason', - 'data': [ 'none', 'request', 'error' ] } + 'data': [ 'none', 'request', 'error' , 'processing' ] } ## # @x-colo-lost-heartbeat: @@ -1376,12 +1380,17 @@ # @mode: COLO running mode. If COLO is running, this field will return # 'primary' or 'secondary'. # +# @last_mode: COLO last running mode. If COLO is running, this field +# will return same like mode field, after failover we can +# use this field to get last colo mode. (since 4.1) +# # @reason: describes the reason for the COLO exit. # # Since: 3.1 ## { 'struct': 'COLOStatus', - 'data': { 'mode': 'COLOMode', 'reason': 'COLOExitReason' } } + 'data': { 'mode': 'COLOMode', 'last_mode': 'COLOMode', + 'reason': 'COLOExitReason' } } ## # @query-colo-status: diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 5f812bb9f2..e2c366e09e 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -111,7 +111,7 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request, if (oob && !(cmd->options & QCO_ALLOW_OOB)) { error_setg(errp, "The command %s does not support OOB", command); - return false; + return NULL; } if (runstate_check(RUN_STATE_PRECONFIG) && diff --git a/qemu-img.c b/qemu-img.c index 5fac840742..8ee63daeae 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1932,7 +1932,7 @@ static int convert_do_copy(ImgConvertState *s) if (!s->has_zero_init && !s->target_has_backing && bdrv_can_write_zeroes_with_unmap(blk_bs(s->target))) { - ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP); + ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK); if (ret == 0) { s->has_zero_init = true; } diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 35dcdcf413..09750a23ce 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -946,6 +946,7 @@ static void write_help(void) " -b, -- write to the VM state rather than the virtual disk\n" " -c, -- write compressed data with blk_write_compressed\n" " -f, -- use Force Unit Access semantics\n" +" -n, -- with -z, don't allow slow fallback\n" " -p, -- ignored for backwards compatibility\n" " -P, -- use different pattern to fill file\n" " -C, -- report statistics in a machine parsable format\n" @@ -964,7 +965,7 @@ static const cmdinfo_t write_cmd = { .perm = BLK_PERM_WRITE, .argmin = 2, .argmax = -1, - .args = "[-bcCfquz] [-P pattern] off len", + .args = "[-bcCfnquz] [-P pattern] off len", .oneline = "writes a number of bytes at a specified offset", .help = write_help, }; @@ -983,7 +984,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv) int64_t total = 0; int pattern = 0xcd; - while ((c = getopt(argc, argv, "bcCfpP:quz")) != -1) { + while ((c = getopt(argc, argv, "bcCfnpP:quz")) != -1) { switch (c) { case 'b': bflag = true; @@ -997,6 +998,9 @@ static int write_f(BlockBackend *blk, int argc, char **argv) case 'f': flags |= BDRV_REQ_FUA; break; + case 'n': + flags |= BDRV_REQ_NO_FALLBACK; + break; case 'p': /* Ignored for backwards compatibility */ break; @@ -1037,6 +1041,11 @@ static int write_f(BlockBackend *blk, int argc, char **argv) return -EINVAL; } + if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) { + printf("-n requires -z to be specified\n"); + return -EINVAL; + } + if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) { printf("-u requires -z to be specified\n"); return -EINVAL; diff --git a/qemu-seccomp.c b/qemu-seccomp.c index 36d5829831..e0a1829b3d 100644 --- a/qemu-seccomp.c +++ b/qemu-seccomp.c @@ -121,58 +121,84 @@ qemu_seccomp(unsigned int operation, unsigned int flags, void *args) #endif } -static uint32_t qemu_seccomp_get_kill_action(void) +static uint32_t qemu_seccomp_get_action(int set) { + switch (set) { + case QEMU_SECCOMP_SET_DEFAULT: + case QEMU_SECCOMP_SET_OBSOLETE: + case QEMU_SECCOMP_SET_PRIVILEGED: + case QEMU_SECCOMP_SET_SPAWN: { #if defined(SECCOMP_GET_ACTION_AVAIL) && defined(SCMP_ACT_KILL_PROCESS) && \ defined(SECCOMP_RET_KILL_PROCESS) - { - uint32_t action = SECCOMP_RET_KILL_PROCESS; + static int kill_process = -1; + if (kill_process == -1) { + uint32_t action = SECCOMP_RET_KILL_PROCESS; - if (qemu_seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &action) == 0) { + if (qemu_seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &action) == 0) { + kill_process = 1; + } + kill_process = 0; + } + if (kill_process == 1) { return SCMP_ACT_KILL_PROCESS; } - } #endif + return SCMP_ACT_TRAP; + } - return SCMP_ACT_TRAP; + case QEMU_SECCOMP_SET_RESOURCECTL: + return SCMP_ACT_ERRNO(EPERM); + + default: + g_assert_not_reached(); + } } -static int seccomp_start(uint32_t seccomp_opts) +static int seccomp_start(uint32_t seccomp_opts, Error **errp) { - int rc = 0; + int rc = -1; unsigned int i = 0; scmp_filter_ctx ctx; - uint32_t action = qemu_seccomp_get_kill_action(); ctx = seccomp_init(SCMP_ACT_ALLOW); if (ctx == NULL) { - rc = -1; + error_setg(errp, "failed to initialize seccomp context"); goto seccomp_return; } rc = seccomp_attr_set(ctx, SCMP_FLTATR_CTL_TSYNC, 1); if (rc != 0) { + error_setg_errno(errp, -rc, + "failed to set seccomp thread synchronization"); goto seccomp_return; } for (i = 0; i < ARRAY_SIZE(blacklist); i++) { + uint32_t action; if (!(seccomp_opts & blacklist[i].set)) { continue; } + action = qemu_seccomp_get_action(blacklist[i].set); rc = seccomp_rule_add_array(ctx, action, blacklist[i].num, blacklist[i].narg, blacklist[i].arg_cmp); if (rc < 0) { + error_setg_errno(errp, -rc, + "failed to add seccomp blacklist rules"); goto seccomp_return; } } rc = seccomp_load(ctx); + if (rc < 0) { + error_setg_errno(errp, -rc, + "failed to load seccomp syscall filter in kernel"); + } seccomp_return: seccomp_release(ctx); - return rc; + return rc < 0 ? -1 : 0; } #ifdef CONFIG_SECCOMP @@ -242,9 +268,7 @@ int parse_sandbox(void *opaque, QemuOpts *opts, Error **errp) } } - if (seccomp_start(seccomp_opts) < 0) { - error_setg(errp, "failed to install seccomp syscall filter " - "in the kernel"); + if (seccomp_start(seccomp_opts, errp) < 0) { return -1; } } diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c index a7df2093aa..632320d72d 100644 --- a/qobject/json-lexer.c +++ b/qobject/json-lexer.c @@ -266,7 +266,7 @@ static inline uint8_t next_state(JSONLexer *lexer, char ch, bool flush, { uint8_t next; - assert(lexer->state <= ARRAY_SIZE(json_lexer)); + assert(lexer->state < ARRAY_SIZE(json_lexer)); next = json_lexer[lexer->state][(uint8_t)ch]; *char_consumed = !flush && !(next & LOOKAHEAD); return next & ~LOOKAHEAD; diff --git a/scripts/minikconf.py b/scripts/minikconf.py index 5421db0ed0..0ffc6c38da 100644 --- a/scripts/minikconf.py +++ b/scripts/minikconf.py @@ -592,7 +592,7 @@ class KconfigParser: if not self.src.startswith(rest, self.cursor): return False length = len(rest) - if self.src[self.cursor + length].isalnum() or self.src[self.cursor + length] == '|': + if self.src[self.cursor + length].isalnum() or self.src[self.cursor + length] == '_': return False self.cursor += length return True diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 504a4771fb..4155782197 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -2028,6 +2028,11 @@ static void arm_max_initfn(Object *obj) t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); cpu->isar.id_isar6 = t; + t = cpu->isar.mvfr2; + t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */ + t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ + cpu->isar.mvfr2 = t; + t = cpu->id_mmfr4; t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */ cpu->id_mmfr4 = t; diff --git a/target/i386/sev.c b/target/i386/sev.c index 20b2d325d8..cd77f6b5d4 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -131,6 +131,17 @@ sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size) { int r; struct kvm_enc_region range; + ram_addr_t offset; + MemoryRegion *mr; + + /* + * The RAM device presents a memory region that should be treated + * as IO region and should not be pinned. + */ + mr = memory_region_from_host(host, &offset); + if (mr && memory_region_is_ram_device(mr)) { + return; + } range.addr = (__u64)(unsigned long)host; range.size = size; diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index fc12b4688e..0707177584 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -2409,6 +2409,12 @@ enum { target_ulong cpu_read_xer(CPUPPCState *env); void cpu_write_xer(CPUPPCState *env, target_ulong xer); +/* + * All 64-bit server processors compliant with arch 2.x, ie. 970 and newer, + * have PPC_SEGMENT_64B. + */ +#define is_book3s_arch2x(ctx) (!!((ctx)->insns_flags & PPC_SEGMENT_64B)) + static inline void cpu_get_tb_cpu_state(CPUPPCState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *flags) { diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h index a2205e1044..c863abc0bf 100644 --- a/target/ppc/helper_regs.h +++ b/target/ppc/helper_regs.h @@ -152,7 +152,7 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value, * - 64-bit embedded implementations do not need any operation to be * performed when PR is set. */ - if ((env->insns_flags & PPC_SEGMENT_64B) && ((value >> MSR_PR) & 1)) { + if (is_book3s_arch2x(env) && ((value >> MSR_PR) & 1)) { value |= (1 << MSR_EE) | (1 << MSR_DR) | (1 << MSR_IR); } #endif diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 98b37cebc2..badc1ae1a3 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -3747,20 +3747,52 @@ static void gen_bcond(DisasContext *ctx, int type) if ((bo & 0x4) == 0) { /* Decrement and test CTR */ TCGv temp = tcg_temp_new(); - if (unlikely(type == BCOND_CTR)) { - gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); - return; - } - tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1); - if (NARROW_MODE(ctx)) { - tcg_gen_ext32u_tl(temp, cpu_ctr); - } else { - tcg_gen_mov_tl(temp, cpu_ctr); - } - if (bo & 0x2) { - tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1); + + if (type == BCOND_CTR) { + /* + * All ISAs up to v3 describe this form of bcctr as invalid but + * some processors, ie. 64-bit server processors compliant with + * arch 2.x, do implement a "test and decrement" logic instead, + * as described in their respective UMs. This logic involves CTR + * to act as both the branch target and a counter, which makes + * it basically useless and thus never used in real code. + * + * This form was hence chosen to trigger extra micro-architectural + * side-effect on real HW needed for the Spectre v2 workaround. + * It is up to guests that implement such workaround, ie. linux, to + * use this form in a way it just triggers the side-effect without + * doing anything else harmful. + */ + if (unlikely(!is_book3s_arch2x(ctx))) { + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); + tcg_temp_free(temp); + tcg_temp_free(target); + return; + } + + if (NARROW_MODE(ctx)) { + tcg_gen_ext32u_tl(temp, cpu_ctr); + } else { + tcg_gen_mov_tl(temp, cpu_ctr); + } + if (bo & 0x2) { + tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1); + } else { + tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1); + } + tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1); } else { - tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1); + tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1); + if (NARROW_MODE(ctx)) { + tcg_gen_ext32u_tl(temp, cpu_ctr); + } else { + tcg_gen_mov_tl(temp, cpu_ctr); + } + if (bo & 0x2) { + tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1); + } else { + tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1); + } } tcg_temp_free(temp); } @@ -3889,7 +3921,7 @@ static void gen_rfi(DisasContext *ctx) /* This instruction doesn't exist anymore on 64-bit server * processors compliant with arch 2.x */ - if (ctx->insns_flags & PPC_SEGMENT_64B) { + if (is_book3s_arch2x(ctx)) { gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); return; } @@ -6511,8 +6543,7 @@ static void gen_msgclr(DisasContext *ctx) GEN_PRIV; #else CHK_HV; - /* 64-bit server processors compliant with arch 2.x */ - if (ctx->insns_flags & PPC_SEGMENT_64B) { + if (is_book3s_arch2x(ctx)) { gen_helper_book3s_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]); } else { gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]); @@ -6526,8 +6557,7 @@ static void gen_msgsnd(DisasContext *ctx) GEN_PRIV; #else CHK_HV; - /* 64-bit server processors compliant with arch 2.x */ - if (ctx->insns_flags & PPC_SEGMENT_64B) { + if (is_book3s_arch2x(ctx)) { gen_helper_book3s_msgsnd(cpu_gpr[rB(ctx->opcode)]); } else { gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]); diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.inc.c index 508e9199c8..489b2436e4 100644 --- a/target/ppc/translate/vsx-impl.inc.c +++ b/target/ppc/translate/vsx-impl.inc.c @@ -356,8 +356,8 @@ static void gen_##name(DisasContext *ctx) \ gen_set_access_type(ctx, ACCESS_INT); \ EA = tcg_temp_new(); \ gen_addr_reg_index(ctx, EA); \ + get_cpu_vsrh(t0, xS(ctx->opcode)); \ gen_qemu_##operation(ctx, t0, EA); \ - set_cpu_vsrh(xS(ctx->opcode), t0); \ tcg_temp_free(EA); \ tcg_temp_free_i64(t0); \ } diff --git a/target/riscv/insn_trans/trans_rvc.inc.c b/target/riscv/insn_trans/trans_rvc.inc.c index 5819f53f90..ebcd977b2f 100644 --- a/target/riscv/insn_trans/trans_rvc.inc.c +++ b/target/riscv/insn_trans/trans_rvc.inc.c @@ -337,7 +337,7 @@ static bool trans_c_fswsp_sdsp(DisasContext *ctx, arg_c_fswsp_sdsp *a) { #ifdef TARGET_RISCV32 /* C.FSWSP */ - arg_fsw a_fsw = { .rs1 = a->rs2, .rs2 = 2, .imm = a->uimm_fswsp }; + arg_fsw a_fsw = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm_fswsp }; return trans_fsw(ctx, &a_fsw); #else /* C.SDSP */ diff --git a/target/riscv/insn_trans/trans_rvm.inc.c b/target/riscv/insn_trans/trans_rvm.inc.c index 204af225f8..47cd6edc72 100644 --- a/target/riscv/insn_trans/trans_rvm.inc.c +++ b/target/riscv/insn_trans/trans_rvm.inc.c @@ -103,7 +103,7 @@ static bool trans_divw(DisasContext *ctx, arg_divw *a) static bool trans_divuw(DisasContext *ctx, arg_divuw *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith_div_w(ctx, a, &gen_divu); + return gen_arith_div_uw(ctx, a, &gen_divu); } static bool trans_remw(DisasContext *ctx, arg_remw *a) @@ -115,6 +115,6 @@ static bool trans_remw(DisasContext *ctx, arg_remw *a) static bool trans_remuw(DisasContext *ctx, arg_remuw *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith_div_w(ctx, a, &gen_remu); + return gen_arith_div_uw(ctx, a, &gen_remu); } #endif diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 049fa65c66..dd763647ea 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -600,6 +600,27 @@ static bool gen_arith_div_w(DisasContext *ctx, arg_r *a, return true; } +static bool gen_arith_div_uw(DisasContext *ctx, arg_r *a, + void(*func)(TCGv, TCGv, TCGv)) +{ + TCGv source1, source2; + source1 = tcg_temp_new(); + source2 = tcg_temp_new(); + + gen_get_gpr(source1, a->rs1); + gen_get_gpr(source2, a->rs2); + tcg_gen_ext32u_tl(source1, source1); + tcg_gen_ext32u_tl(source2, source2); + + (*func)(source1, source1, source2); + + tcg_gen_ext32s_tl(source1, source1); + gen_set_gpr(a->rd, source1); + tcg_temp_free(source1); + tcg_temp_free(source2); + return true; +} + #endif static bool gen_arith(DisasContext *ctx, arg_r *a, diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 77bc04d6b0..65561d2c49 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1041,7 +1041,6 @@ static bool break_dependency(struct slot_prop *a, copy[n].resource = b->in[j].resource; copy[n].arg = b->arg + index; ++n; - ++i; ++j; rv = true; } diff --git a/target/xtensa/xtensa-semi.c b/target/xtensa/xtensa-semi.c index 2f76216276..5f5ce4f344 100644 --- a/target/xtensa/xtensa-semi.c +++ b/target/xtensa/xtensa-semi.c @@ -202,7 +202,6 @@ void HELPER(simcall)(CPUXtensaState *env) switch (regs[2]) { case TARGET_SYS_exit: - qemu_log("exit(%d) simcall\n", regs[3]); exit(regs[3]); break; diff --git a/tests/Makefile.include b/tests/Makefile.include index 852f17b8c7..6b904d7430 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -195,7 +195,6 @@ check-qtest-i386-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF) check-qtest-i386-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF) check-qtest-i386-$(CONFIG_RTL8139_PCI) += tests/test-filter-redirector$(EXESUF) check-qtest-i386-y += tests/migration-test$(EXESUF) -check-qtest-i386-y += tests/test-announce-self$(EXESUF) check-qtest-i386-y += tests/test-x86-cpuid-compat$(EXESUF) check-qtest-i386-y += tests/numa-test$(EXESUF) check-qtest-x86_64-y += $(check-qtest-i386-y) @@ -232,7 +231,6 @@ check-qtest-ppc64-y += $(check-qtest-ppc-y) check-qtest-ppc64-$(CONFIG_PSERIES) += tests/device-plug-test$(EXESUF) check-qtest-ppc64-$(CONFIG_POWERNV) += tests/pnv-xscom-test$(EXESUF) check-qtest-ppc64-y += tests/migration-test$(EXESUF) -check-qtest-ppc64-y += tests/test-announce-self$(EXESUF) check-qtest-ppc64-$(CONFIG_PSERIES) += tests/rtas-test$(EXESUF) check-qtest-ppc64-$(CONFIG_SLIRP) += tests/pxe-test$(EXESUF) check-qtest-ppc64-$(CONFIG_USB_UHCI) += tests/usb-hcd-uhci-test$(EXESUF) @@ -817,7 +815,6 @@ tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y) tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y) tests/cpu-plug-test$(EXESUF): tests/cpu-plug-test.o tests/migration-test$(EXESUF): tests/migration-test.o -tests/test-announce-self$(EXESUF): tests/test-announce-self.o tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y) tests/test-keyval$(EXESUF): tests/test-keyval.o $(test-util-obj-y) $(test-qapi-obj-y) diff --git a/tests/qemu-iotests/248 b/tests/qemu-iotests/248 new file mode 100755 index 0000000000..f26b4bb2aa --- /dev/null +++ b/tests/qemu-iotests/248 @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# +# Test resume mirror after auto pause on ENOSPC +# +# Copyright (c) 2019 Virtuozzo International GmbH. 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/>. +# + +import iotests +from iotests import qemu_img_create, qemu_io, file_path, filter_qmp_testfiles + +iotests.verify_image_format(supported_fmts=['qcow2']) + +source, target = file_path('source', 'target') +size = 5 * 1024 * 1024 +limit = 2 * 1024 * 1024 + +qemu_img_create('-f', iotests.imgfmt, source, str(size)) +qemu_img_create('-f', iotests.imgfmt, target, str(size)) +qemu_io('-c', 'write 0 {}'.format(size), source) + +# raw format don't like empty files +qemu_io('-c', 'write 0 {}'.format(size), target) + +vm = iotests.VM().add_drive(source) +vm.launch() + +blockdev_opts = { + 'driver': iotests.imgfmt, + 'node-name': 'target', + 'file': { + 'driver': 'raw', + 'size': limit, + 'file': { + 'driver': 'file', + 'filename': target + } + } +} +vm.qmp_log('blockdev-add', filters=[filter_qmp_testfiles], **blockdev_opts) + +vm.qmp_log('blockdev-mirror', device='drive0', sync='full', target='target', + on_target_error='enospc') + +vm.event_wait('JOB_STATUS_CHANGE', timeout=3.0, + match={'data': {'status': 'paused'}}) + +# drop other cached events, to not interfere with further wait for 'running' +vm.get_qmp_events() + +del blockdev_opts['file']['size'] +vm.qmp_log('x-blockdev-reopen', filters=[filter_qmp_testfiles], + **blockdev_opts) + +vm.qmp_log('block-job-resume', device='drive0') +vm.event_wait('JOB_STATUS_CHANGE', timeout=1.0, + match={'data': {'status': 'running'}}) + +vm.shutdown() diff --git a/tests/qemu-iotests/248.out b/tests/qemu-iotests/248.out new file mode 100644 index 0000000000..369b25bf26 --- /dev/null +++ b/tests/qemu-iotests/248.out @@ -0,0 +1,8 @@ +{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "raw", "file": {"driver": "file", "filename": "TEST_DIR/PID-target"}, "size": 2097152}, "node-name": "target"}} +{"return": {}} +{"execute": "blockdev-mirror", "arguments": {"device": "drive0", "on-target-error": "enospc", "sync": "full", "target": "target"}} +{"return": {}} +{"execute": "x-blockdev-reopen", "arguments": {"driver": "qcow2", "file": {"driver": "raw", "file": {"driver": "file", "filename": "TEST_DIR/PID-target"}}, "node-name": "target"}} +{"return": {}} +{"execute": "block-job-resume", "arguments": {"device": "drive0"}} +{"return": {}} diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index d192abaecf..41da10c6cf 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -246,3 +246,4 @@ 245 rw auto 246 rw auto quick 247 rw auto quick +248 rw auto quick diff --git a/tests/tcg/xtensa/Makefile.softmmu-target b/tests/tcg/xtensa/Makefile.softmmu-target index 86bb47db77..8212d96b81 100644 --- a/tests/tcg/xtensa/Makefile.softmmu-target +++ b/tests/tcg/xtensa/Makefile.softmmu-target @@ -8,7 +8,7 @@ XTENSA_SRC = $(SRC_PATH)/tests/tcg/xtensa XTENSA_ALL = $(filter-out $(XTENSA_SRC)/linker.ld.S,$(wildcard $(XTENSA_SRC)/*.S)) XTENSA_TESTS = $(patsubst $(XTENSA_SRC)/%.S, %, $(XTENSA_ALL)) # Filter out common blobs and broken tests -XTENSA_BROKEN_TESTS = crt vectors test_boolean test_pipeline test_fail +XTENSA_BROKEN_TESTS = crt vectors XTENSA_USABLE_TESTS = $(filter-out $(XTENSA_BROKEN_TESTS), $(XTENSA_TESTS)) # add to the list of tests diff --git a/tests/tcg/xtensa/test_fail.S b/tests/tcg/xtensa/test_fail.S deleted file mode 100644 index 1c26d50790..0000000000 --- a/tests/tcg/xtensa/test_fail.S +++ /dev/null @@ -1,9 +0,0 @@ -#include "macros.inc" - -test_suite fail - -test fail - test_fail -test_end - -test_suite_end diff --git a/tests/tcg/xtensa/test_flix.S b/tests/tcg/xtensa/test_flix.S index 7c259e7018..7af06b2b88 100644 --- a/tests/tcg/xtensa/test_flix.S +++ b/tests/tcg/xtensa/test_flix.S @@ -55,6 +55,23 @@ test sum .previous test_end +test rep_dependency + + { + movi a2, 1 + movi a3, 2 + nop + } + { + or a2, a3, a3 + or a3, a2, a2 + nop + } + assert eqi, a2, 2 + assert eqi, a3, 1 + +test_end + #endif test_suite_end diff --git a/tests/tcg/xtensa/test_pipeline.S b/tests/tcg/xtensa/test_pipeline.S deleted file mode 100644 index f418c11974..0000000000 --- a/tests/tcg/xtensa/test_pipeline.S +++ /dev/null @@ -1,157 +0,0 @@ -#include "macros.inc" - -.purgem test -.macro test name - movi a2, 1f - movi a3, 99f -0: - ipf a2, 0 - ipf a2, 4 - ipf a2, 8 - ipf a2, 12 - addi a2, a2, 16 - blt a2, a3, 0b - j 1f - .align 4 -1: -.endm - -test_suite pipeline - -test register_no_stall - rsr a3, ccount - add a5, a6, a6 - add a6, a5, a5 - rsr a4, ccount - sub a3, a4, a3 - assert eqi, a3, 3 -test_end - -test register_stall - l32i a5, a1, 0 /* data cache preload */ - nop - rsr a3, ccount - l32i a5, a1, 0 - add a6, a5, a5 /* M-to-E interlock */ - rsr a4, ccount - sub a3, a4, a3 - assert eqi, a3, 4 -test_end - -test j0_stall - rsr a3, ccount - j 1f /* E + 2-cycle penalty */ -1: - rsr a4, ccount /* E */ - sub a3, a4, a3 - assert eqi, a3, 4 -test_end - -test j1_stall - rsr a3, ccount - j 1f - nop -1: - rsr a4, ccount - sub a3, a4, a3 - assert eqi, a3, 4 -test_end - -test j5_stall - rsr a3, ccount - j 1f - nop - nop - nop - nop - nop -1: - rsr a4, ccount - sub a3, a4, a3 - assert eqi, a3, 4 -test_end - -test b_no_stall - movi a5, 1 - rsr a3, ccount - beqi a5, 2, 1f - rsr a4, ccount - sub a3, a4, a3 - assert eqi, a3, 2 -1: -test_end - -test b1_stall - movi a5, 1 - rsr a3, ccount - beqi a5, 1, 1f - nop -1: - rsr a4, ccount - sub a3, a4, a3 - assert eqi, a3, 4 -test_end - -test b5_stall - movi a5, 1 - rsr a3, ccount - beqi a5, 1, 1f - nop - nop - nop - nop - nop -1: - rsr a4, ccount - sub a3, a4, a3 - assert eqi, a3, 4 -test_end - -/* PS *SYNC */ - -test ps_dsync - rsr a5, ps - isync - rsr a3, ccount - wsr a5, ps - dsync - rsr a4, ccount - sub a3, a4, a3 - assert eqi, a3, 5 -test_end - -test ps_esync - rsr a5, ps - isync - rsr a3, ccount - wsr a5, ps - esync - rsr a4, ccount - sub a3, a4, a3 - assert eqi, a3, 5 -test_end - -test ps_rsync - rsr a5, ps - isync - rsr a3, ccount - wsr a5, ps - rsync - rsr a4, ccount - sub a3, a4, a3 - assert eqi, a3, 5 -test_end - -test ps_isync - rsr a5, ps - isync - rsr a3, ccount - wsr a5, ps - isync - rsr a4, ccount - sub a3, a4, a3 - movi a4, 9 - assert eq, a3, a4 -test_end - -test_suite_end diff --git a/tests/test-announce-self.c b/tests/test-announce-self.c deleted file mode 100644 index 0e6d466aa4..0000000000 --- a/tests/test-announce-self.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * QTest testcase for qemu_announce_self - * - * Copyright (c) 2017 Red hat, Inc. - * Copyright (c) 2014 SUSE LINUX Products GmbH - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "libqtest.h" -#include "qapi/qmp/qdict.h" -#include "qemu-common.h" -#include "qemu/sockets.h" -#include "qemu/iov.h" -#include "libqos/libqos-pc.h" -#include "libqos/libqos-spapr.h" - -#ifndef ETH_P_RARP -#define ETH_P_RARP 0x8035 -#endif - - -static void test_announce(QTestState *qs, int socket) -{ - char buffer[60]; - int len; - QDict *rsp; - int ret; - uint16_t *proto = (uint16_t *)&buffer[12]; - - rsp = qtest_qmp(qs, "{ 'execute' : 'announce-self', " - " 'arguments': {" - " 'initial': 50, 'max': 550," - " 'rounds': 10, 'step': 50 } }"); - assert(!qdict_haskey(rsp, "error")); - qobject_unref(rsp); - - /* Catch the packet and make sure it's a RARP */ - ret = qemu_recv(socket, &len, sizeof(len), 0); - g_assert_cmpint(ret, ==, sizeof(len)); - len = ntohl(len); - - ret = qemu_recv(socket, buffer, len, 0); - g_assert_cmpint(*proto, ==, htons(ETH_P_RARP)); -} - -static void setup(gconstpointer data) -{ - QTestState *qs; - void (*func) (QTestState *qs, int socket) = data; - int sv[2], ret; - - ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sv); - g_assert_cmpint(ret, !=, -1); - - qs = qtest_initf("-netdev socket,fd=%d,id=hs0 -device " - "virtio-net-pci,netdev=hs0", sv[1]); - func(qs, sv[0]); - - /* End test */ - close(sv[0]); - qtest_quit(qs); -} - -int main(int argc, char **argv) -{ - g_test_init(&argc, &argv, NULL); - qtest_add_data_func("/virtio/net/test_announce_self", test_announce, setup); - - return g_test_run(); -} diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c index c58e670e2f..0d956f36fe 100644 --- a/tests/virtio-net-test.c +++ b/tests/virtio-net-test.c @@ -15,6 +15,10 @@ #include "libqos/qgraph.h" #include "libqos/virtio-net.h" +#ifndef ETH_P_RARP +#define ETH_P_RARP 0x8035 +#endif + #define PCI_SLOT_HP 0x06 #define PCI_SLOT 0x04 @@ -168,6 +172,31 @@ static void hotplug(void *obj, void *data, QGuestAllocator *t_alloc) } } +static void announce_self(void *obj, void *data, QGuestAllocator *t_alloc) +{ + int *sv = data; + char buffer[60]; + int len; + QDict *rsp; + int ret; + uint16_t *proto = (uint16_t *)&buffer[12]; + + rsp = qmp("{ 'execute' : 'announce-self', " + " 'arguments': {" + " 'initial': 50, 'max': 550," + " 'rounds': 10, 'step': 50 } }"); + assert(!qdict_haskey(rsp, "error")); + qobject_unref(rsp); + + /* Catch the packet and make sure it's a RARP */ + ret = qemu_recv(sv[0], &len, sizeof(len), 0); + g_assert_cmpint(ret, ==, sizeof(len)); + len = ntohl(len); + + ret = qemu_recv(sv[0], buffer, len, 0); + g_assert_cmpint(*proto, ==, htons(ETH_P_RARP)); +} + static void virtio_net_test_cleanup(void *sockets) { int *sv = sockets; @@ -233,6 +262,7 @@ static void register_virtio_net_test(void) qos_add_test("basic", "virtio-net", send_recv_test, &opts); qos_add_test("rx_stop_cont", "virtio-net", stop_cont_test, &opts); #endif + qos_add_test("announce-self", "virtio-net", announce_self, &opts); /* These tests do not need a loopback backend. */ opts.before = virtio_net_test_setup_nosocket; diff --git a/util/error.c b/util/error.c index b5ccbd8eac..934a78e1b1 100644 --- a/util/error.c +++ b/util/error.c @@ -103,10 +103,6 @@ void error_setg_errno_internal(Error **errp, va_list ap; int saved_errno = errno; - if (errp == NULL) { - return; - } - va_start(ap, fmt); error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, os_errno != 0 ? strerror(os_errno) : NULL); |